line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#234567890123456789012345678901234567890123456789012345678901234567890 |
2
|
|
|
|
|
|
|
package Tk::DynaTabFrame; |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
require 5.008; |
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
3881
|
use Tk; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use Tk ':variables'; |
8
|
|
|
|
|
|
|
use Tk::Balloon; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use base qw (Tk::Derived Tk::Frame); |
11
|
|
|
|
|
|
|
use vars qw ($VERSION); |
12
|
|
|
|
|
|
|
use strict; |
13
|
|
|
|
|
|
|
use Carp; |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
$VERSION = '0.23'; |
16
|
|
|
|
|
|
|
# |
17
|
|
|
|
|
|
|
# indexes of our tab properties |
18
|
|
|
|
|
|
|
# |
19
|
|
|
|
|
|
|
use constant DTF_IDX_WIDGET => 0; |
20
|
|
|
|
|
|
|
use constant DTF_IDX_CAPTION => 1; |
21
|
|
|
|
|
|
|
use constant DTF_IDX_COLOR => 2; |
22
|
|
|
|
|
|
|
use constant DTF_IDX_ROW => 3; |
23
|
|
|
|
|
|
|
use constant DTF_IDX_COL => 4; |
24
|
|
|
|
|
|
|
use constant DTF_IDX_FRAME => 5; |
25
|
|
|
|
|
|
|
use constant DTF_IDX_WIDTH => 6; |
26
|
|
|
|
|
|
|
use constant DTF_IDX_HEIGHT => 7; |
27
|
|
|
|
|
|
|
use constant DTF_IDX_RAISECOLOR => 8; |
28
|
|
|
|
|
|
|
use constant DTF_IDX_RAISECMD => 9; |
29
|
|
|
|
|
|
|
use constant DTF_IDX_LABEL => 10; |
30
|
|
|
|
|
|
|
use constant DTF_IDX_FLASH_COLOR => 11; |
31
|
|
|
|
|
|
|
use constant DTF_IDX_FLASH_INTVL => 12; |
32
|
|
|
|
|
|
|
use constant DTF_IDX_FLASH_TIME => 13; |
33
|
|
|
|
|
|
|
use constant DTF_IDX_FLASH_ID => 14; |
34
|
|
|
|
|
|
|
use constant DTF_IDX_FLASHED => 15; |
35
|
|
|
|
|
|
|
use constant DTF_IDX_HIDDEN => 16; |
36
|
|
|
|
|
|
|
use constant DTF_IDX_TABTIP => 17; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my $close_xpm = << 'end-of-close-xpm'; |
39
|
|
|
|
|
|
|
/* XPM */ |
40
|
|
|
|
|
|
|
static char * close_xpm[] = { |
41
|
|
|
|
|
|
|
"8 8 3 1", |
42
|
|
|
|
|
|
|
" s None c None", |
43
|
|
|
|
|
|
|
". c #000000000000", |
44
|
|
|
|
|
|
|
"X c #E0E0FFFFE0E0", |
45
|
|
|
|
|
|
|
".. ..", |
46
|
|
|
|
|
|
|
" .. .. ", |
47
|
|
|
|
|
|
|
" .... ", |
48
|
|
|
|
|
|
|
" .. ", |
49
|
|
|
|
|
|
|
" .. ", |
50
|
|
|
|
|
|
|
" .... ", |
51
|
|
|
|
|
|
|
" .. .. ", |
52
|
|
|
|
|
|
|
".. .."}; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
end-of-close-xpm |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
my $close_xpm_6 = << 'end-of-close-xpm-6'; |
57
|
|
|
|
|
|
|
/* XPM */ |
58
|
|
|
|
|
|
|
static char * close_xpm[] = { |
59
|
|
|
|
|
|
|
"6 6 3 1", |
60
|
|
|
|
|
|
|
" s None c None", |
61
|
|
|
|
|
|
|
". c #000000000000", |
62
|
|
|
|
|
|
|
"X c #E0E0FFFFE0E0", |
63
|
|
|
|
|
|
|
".. ..", |
64
|
|
|
|
|
|
|
" .... ", |
65
|
|
|
|
|
|
|
" .. ", |
66
|
|
|
|
|
|
|
" .. ", |
67
|
|
|
|
|
|
|
" .... ", |
68
|
|
|
|
|
|
|
".. ..",}; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
end-of-close-xpm-6 |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# |
73
|
|
|
|
|
|
|
# map of tabframe directives based on |
74
|
|
|
|
|
|
|
# tab orientation |
75
|
|
|
|
|
|
|
# |
76
|
|
|
|
|
|
|
use constant DTF_TAB_TABSIDE => 0; |
77
|
|
|
|
|
|
|
use constant DTF_TAB_TABFILL => 1; |
78
|
|
|
|
|
|
|
use constant DTF_TAB_TABANCHOR => 2; |
79
|
|
|
|
|
|
|
use constant DTF_TAB_TABSIZER => 3; |
80
|
|
|
|
|
|
|
use constant DTF_TAB_CLIENTSIDE => 4; |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
my %tabalign = ( |
83
|
|
|
|
|
|
|
# tabframe -side, tabframe -fill, tabframe -anchor, |
84
|
|
|
|
|
|
|
# tabframe sizing option, clientframe -side |
85
|
|
|
|
|
|
|
nw => [ 'top', 'x', 'nw', '-height', 'bottom'], |
86
|
|
|
|
|
|
|
ne => [ 'top', 'x', 'ne', '-height', 'bottom'], |
87
|
|
|
|
|
|
|
sw => [ 'bottom', 'x', 'sw', '-height', 'top'], |
88
|
|
|
|
|
|
|
se => [ 'bottom', 'x', 'se', '-height', 'top'], |
89
|
|
|
|
|
|
|
en => [ 'right', 'y', 'ne', '-width', 'left'], |
90
|
|
|
|
|
|
|
es => [ 'right', 'y', 'se', '-width', 'left'], |
91
|
|
|
|
|
|
|
wn => [ 'left', 'y', 'nw', '-width', 'right'], |
92
|
|
|
|
|
|
|
ws => [ 'left', 'y', 'sw', '-width', 'right'], |
93
|
|
|
|
|
|
|
); |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# |
96
|
|
|
|
|
|
|
# bitmaps for border requirements |
97
|
|
|
|
|
|
|
# based on tab orientations |
98
|
|
|
|
|
|
|
# bit 0 => Left |
99
|
|
|
|
|
|
|
# bit 1 => Right |
100
|
|
|
|
|
|
|
# bit 2 => Top |
101
|
|
|
|
|
|
|
# bit 3 => Bottom |
102
|
|
|
|
|
|
|
# 'p' sides are for pseudo tabs |
103
|
|
|
|
|
|
|
# |
104
|
|
|
|
|
|
|
my %borders = qw( |
105
|
|
|
|
|
|
|
nw 7 |
106
|
|
|
|
|
|
|
ne 7 |
107
|
|
|
|
|
|
|
sw 11 |
108
|
|
|
|
|
|
|
se 11 |
109
|
|
|
|
|
|
|
en 14 |
110
|
|
|
|
|
|
|
es 14 |
111
|
|
|
|
|
|
|
wn 13 |
112
|
|
|
|
|
|
|
ws 13 |
113
|
|
|
|
|
|
|
pnw 6 |
114
|
|
|
|
|
|
|
pne 5 |
115
|
|
|
|
|
|
|
psw 10 |
116
|
|
|
|
|
|
|
pse 9 |
117
|
|
|
|
|
|
|
pen 10 |
118
|
|
|
|
|
|
|
pes 6 |
119
|
|
|
|
|
|
|
pwn 9 |
120
|
|
|
|
|
|
|
pws 5 |
121
|
|
|
|
|
|
|
); |
122
|
|
|
|
|
|
|
# |
123
|
|
|
|
|
|
|
# pack directives for the tab contents |
124
|
|
|
|
|
|
|
# [ closebtn_side, |
125
|
|
|
|
|
|
|
# closebtn_anchor, |
126
|
|
|
|
|
|
|
# button_side, |
127
|
|
|
|
|
|
|
# button_anchor, |
128
|
|
|
|
|
|
|
# pseudo_anchor |
129
|
|
|
|
|
|
|
# tab direction |
130
|
|
|
|
|
|
|
# ] |
131
|
|
|
|
|
|
|
# |
132
|
|
|
|
|
|
|
use constant DTF_ORIENT_CLOSESIDE => 0; |
133
|
|
|
|
|
|
|
use constant DTF_ORIENT_CLOSEANCHOR => 1; |
134
|
|
|
|
|
|
|
use constant DTF_ORIENT_BTNSIDE => 2; |
135
|
|
|
|
|
|
|
use constant DTF_ORIENT_BTNANCHOR => 3; |
136
|
|
|
|
|
|
|
use constant DTF_ORIENT_PSEUDOANCHOR => 4; |
137
|
|
|
|
|
|
|
use constant DTF_ORIENT_DIRECTION => 5; |
138
|
|
|
|
|
|
|
use constant DTF_ORIENT_ALIGN => 6; |
139
|
|
|
|
|
|
|
use constant DTF_ORIENT_DOWNWARD => 7; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
use constant DTF_MAX_ROWS => 20; |
142
|
|
|
|
|
|
|
use constant DTF_DFLT_TIPTIME => 450; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
my %taborient = ( |
145
|
|
|
|
|
|
|
'nw', [ 'right', 'ne', 'right', 's', 'e', 1, 0, 1, ], |
146
|
|
|
|
|
|
|
'ne', [ 'right', 'ne', 'right', 's', 'w', 1, 0, 1, ], |
147
|
|
|
|
|
|
|
'sw', [ 'right', 'se', 'right', 'n', 'e', 1, 1, 0, ], |
148
|
|
|
|
|
|
|
'se', [ 'right', 'se', 'right', 'n', 'w', 1, 1, 0, ], |
149
|
|
|
|
|
|
|
'en', [ 'top', 'ne', 'top', 's', 's', 0, 0, 0, ], |
150
|
|
|
|
|
|
|
'es', [ 'top', 'ne', 'top', 's', 'n', 0, 0, 0, ], |
151
|
|
|
|
|
|
|
'wn', [ 'top', 'nw', 'top', 's', 's', 0, 1, 1, ], |
152
|
|
|
|
|
|
|
'ws', [ 'top', 'nw', 'top', 's', 'n', 0, 1, 1, ], |
153
|
|
|
|
|
|
|
); |
154
|
|
|
|
|
|
|
# |
155
|
|
|
|
|
|
|
# page options for Tk::Notebook compatibility |
156
|
|
|
|
|
|
|
# |
157
|
|
|
|
|
|
|
my %page_opts = ( |
158
|
|
|
|
|
|
|
'-tabcolor', DTF_IDX_COLOR, |
159
|
|
|
|
|
|
|
'-raisecolor', DTF_IDX_RAISECOLOR, |
160
|
|
|
|
|
|
|
'-image', '-image', |
161
|
|
|
|
|
|
|
'-label', DTF_IDX_LABEL, |
162
|
|
|
|
|
|
|
'-raisecmd', DTF_IDX_RAISECMD, |
163
|
|
|
|
|
|
|
'-state', '-state', |
164
|
|
|
|
|
|
|
'-tabtip', DTF_IDX_TABTIP, |
165
|
|
|
|
|
|
|
'-hidden', DTF_IDX_HIDDEN |
166
|
|
|
|
|
|
|
); |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
Tk::Widget->Construct ('DynaTabFrame'); |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
sub Populate { |
171
|
|
|
|
|
|
|
my $this = shift; |
172
|
|
|
|
|
|
|
$this->ConfigSpecs( |
173
|
|
|
|
|
|
|
'-borderwidth' => [['SELF', 'PASSIVE'], |
174
|
|
|
|
|
|
|
'borderwidth', 'BorderWidth', '1'], |
175
|
|
|
|
|
|
|
'-tabcurve' => [['SELF', 'PASSIVE'], |
176
|
|
|
|
|
|
|
'tabcurve', 'TabCurve', 2], |
177
|
|
|
|
|
|
|
'-padx' => [['SELF', 'PASSIVE'], 'padx', 'padx', 5], |
178
|
|
|
|
|
|
|
'-pady' => [['SELF', 'PASSIVE'], 'pady', 'pady', 5], |
179
|
|
|
|
|
|
|
# |
180
|
|
|
|
|
|
|
# for Tk::Notebook compatibility |
181
|
|
|
|
|
|
|
# |
182
|
|
|
|
|
|
|
'-tabpadx' => [['SELF', 'PASSIVE'], 'tabpadx', 'tabpadx', 2], |
183
|
|
|
|
|
|
|
'-tabpady' => [['SELF', 'PASSIVE'], 'tabpady', 'tabpady', 2], |
184
|
|
|
|
|
|
|
'-font' => ['METHOD', 'font', 'Font', undef], |
185
|
|
|
|
|
|
|
'-current' => ['METHOD'], |
186
|
|
|
|
|
|
|
'-raised' => ['METHOD'], |
187
|
|
|
|
|
|
|
'-raised_name' => ['METHOD'], |
188
|
|
|
|
|
|
|
'-tabs' => ['METHOD'], |
189
|
|
|
|
|
|
|
'-delay' => [['SELF', 'PASSIVE'], 'delay', 'Delay', '200'], |
190
|
|
|
|
|
|
|
'-raisecmd' => [['SELF', 'PASSIVE'], 'raisecmd', 'RaiseCmd', undef], |
191
|
|
|
|
|
|
|
'-tablock' => [['SELF', 'PASSIVE'], 'tablock', 'tablock', undef], |
192
|
|
|
|
|
|
|
'-tabrotate' => [['SELF', 'PASSIVE'], 'tabrotate', 'tabrotate', 1], |
193
|
|
|
|
|
|
|
'-tabside' => ['METHOD'], |
194
|
|
|
|
|
|
|
'-tabclose' => ['METHOD'], |
195
|
|
|
|
|
|
|
'-tabscroll' => ['METHOD'], |
196
|
|
|
|
|
|
|
'-tabcolor' => [['SELF', 'PASSIVE'], 'tabcolor', 'tabcolor', undef], |
197
|
|
|
|
|
|
|
'-tabtip' => [['SELF', 'PASSIVE'], 'tabtip', 'tabtip', undef], |
198
|
|
|
|
|
|
|
'-tiptime' => ['METHOD'], |
199
|
|
|
|
|
|
|
'-tipcolor' => ['METHOD'], |
200
|
|
|
|
|
|
|
'-textalign' => [['SELF', 'PASSIVE'], 'textalign', 'textalign', 1], |
201
|
|
|
|
|
|
|
'-backpagecolor' => [['SELF', 'PASSIVE'], 'tabcolor', 'tabcolor', undef], |
202
|
|
|
|
|
|
|
'-raisecolor' => [['SELF', 'PASSIVE'], 'raisecolor', 'raisecolor', undef], |
203
|
|
|
|
|
|
|
); |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
$this->SUPER::Populate(@_); |
206
|
|
|
|
|
|
|
# |
207
|
|
|
|
|
|
|
# set default tab orientation |
208
|
|
|
|
|
|
|
# |
209
|
|
|
|
|
|
|
$this->{Side} = 'nw'; |
210
|
|
|
|
|
|
|
$this->{_tiptime} = DTF_DFLT_TIPTIME; |
211
|
|
|
|
|
|
|
$this->{_tipcolor} = 'white'; |
212
|
|
|
|
|
|
|
# |
213
|
|
|
|
|
|
|
# get tab alignment info |
214
|
|
|
|
|
|
|
# |
215
|
|
|
|
|
|
|
my ($tabside, $tabfill, $tabanchor, $tabsize, $clientside) = |
216
|
|
|
|
|
|
|
@{$tabalign{$this->{Side}}}; |
217
|
|
|
|
|
|
|
# |
218
|
|
|
|
|
|
|
# ButtonFrame is where the tabs are |
219
|
|
|
|
|
|
|
# |
220
|
|
|
|
|
|
|
my $ButtonFrame = $this->{ButtonFrame} = $this->Component( |
221
|
|
|
|
|
|
|
'Frame' => 'ButtonFrame', |
222
|
|
|
|
|
|
|
-borderwidth => 0, |
223
|
|
|
|
|
|
|
-relief => 'flat', |
224
|
|
|
|
|
|
|
$tabsize => 40, |
225
|
|
|
|
|
|
|
)->pack( |
226
|
|
|
|
|
|
|
-anchor => $tabanchor, |
227
|
|
|
|
|
|
|
-side => $tabside, |
228
|
|
|
|
|
|
|
-fill => $tabfill, |
229
|
|
|
|
|
|
|
); |
230
|
|
|
|
|
|
|
# |
231
|
|
|
|
|
|
|
# create the frame we return to the app |
232
|
|
|
|
|
|
|
# |
233
|
|
|
|
|
|
|
my $ClientFrame = $this->{ClientFrame} = $this->Component( |
234
|
|
|
|
|
|
|
'Frame' => 'TabChildFrame', |
235
|
|
|
|
|
|
|
-relief => 'flat', |
236
|
|
|
|
|
|
|
-borderwidth => 0, |
237
|
|
|
|
|
|
|
-height => 60, |
238
|
|
|
|
|
|
|
)->pack( |
239
|
|
|
|
|
|
|
-side => $clientside, |
240
|
|
|
|
|
|
|
-expand => 1, |
241
|
|
|
|
|
|
|
-fill => 'both', |
242
|
|
|
|
|
|
|
); |
243
|
|
|
|
|
|
|
# |
244
|
|
|
|
|
|
|
# a pseudo-frame used to make the raised tab smoothly connect |
245
|
|
|
|
|
|
|
# to the client frame |
246
|
|
|
|
|
|
|
# |
247
|
|
|
|
|
|
|
my $Connector = $this->Component( |
248
|
|
|
|
|
|
|
'Frame' => 'Connector', |
249
|
|
|
|
|
|
|
-relief => 'flat' |
250
|
|
|
|
|
|
|
); |
251
|
|
|
|
|
|
|
# |
252
|
|
|
|
|
|
|
# list of all our current clients |
253
|
|
|
|
|
|
|
# |
254
|
|
|
|
|
|
|
$this->{ClientList} = [ ]; |
255
|
|
|
|
|
|
|
# |
256
|
|
|
|
|
|
|
# a quick lookup by caption |
257
|
|
|
|
|
|
|
# |
258
|
|
|
|
|
|
|
$this->{ClientHash} = {}; |
259
|
|
|
|
|
|
|
# |
260
|
|
|
|
|
|
|
# a quick lookup of row numbers |
261
|
|
|
|
|
|
|
# so a raise() can just move entire rows around |
262
|
|
|
|
|
|
|
# create first empty row |
263
|
|
|
|
|
|
|
# |
264
|
|
|
|
|
|
|
$this->{RowList} = [ [] ]; |
265
|
|
|
|
|
|
|
# |
266
|
|
|
|
|
|
|
# plug into the configure event so we get resizes |
267
|
|
|
|
|
|
|
# |
268
|
|
|
|
|
|
|
$this->{OldWidth} = $ButtonFrame->reqwidth(); |
269
|
|
|
|
|
|
|
$this->{OldHeight} = $ButtonFrame->reqheight(); |
270
|
|
|
|
|
|
|
$this->bind("" => sub { $this->ConfigDebounce; }); |
271
|
|
|
|
|
|
|
# |
272
|
|
|
|
|
|
|
# generate the close button |
273
|
|
|
|
|
|
|
# |
274
|
|
|
|
|
|
|
my $scrwd = $this->screenwidth; |
275
|
|
|
|
|
|
|
$this->{CloseImage} = $this->Pixmap(-data => (($scrwd <= 1024) ? $close_xpm_6 : $close_xpm)); |
276
|
|
|
|
|
|
|
return $this; |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
sub ConfigDebounce { |
280
|
|
|
|
|
|
|
my ($this) = @_; |
281
|
|
|
|
|
|
|
my $w = $Tk::event->w; |
282
|
|
|
|
|
|
|
my $h = $Tk::event->h; |
283
|
|
|
|
|
|
|
# |
284
|
|
|
|
|
|
|
# only post event if we've changed width/height |
285
|
|
|
|
|
|
|
# |
286
|
|
|
|
|
|
|
return 1 if (($this->{OldWidth} == $w) && ($this->{OldHeight} == $h)); |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
$this->{LastConfig} = Tk::timeofday; |
289
|
|
|
|
|
|
|
$this->{LastWidth} = $w; |
290
|
|
|
|
|
|
|
$this->{LastHeight} = $h; |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
$this->afterCancel($this->{LastAfterID}) |
293
|
|
|
|
|
|
|
if defined($this->{LastAfterID}); |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
$this->{LastAfterID} = $this->after(200, # $this->cget('-delay'), |
296
|
|
|
|
|
|
|
sub { |
297
|
|
|
|
|
|
|
$this->TabReconfig(); |
298
|
|
|
|
|
|
|
delete $this->{LastAfterID}; |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
); |
301
|
|
|
|
|
|
|
1; |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub TabCreate { |
305
|
|
|
|
|
|
|
my ($this, $Caption, $Color, $RaiseColor, $Image, $Text, $RaiseCmd) = @_; |
306
|
|
|
|
|
|
|
# |
307
|
|
|
|
|
|
|
# always add at (0,0) |
308
|
|
|
|
|
|
|
# |
309
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
310
|
|
|
|
|
|
|
my $rows = $this->{RowList}; |
311
|
|
|
|
|
|
|
my $ButtonFrame = $this->{ButtonFrame}; |
312
|
|
|
|
|
|
|
# |
313
|
|
|
|
|
|
|
# create some pseudo tabs |
314
|
|
|
|
|
|
|
# note we only create DTF_MAX_ROWS, so if we have > DTF_MAX_ROWS+1 |
315
|
|
|
|
|
|
|
# tab rows, we're in trouble |
316
|
|
|
|
|
|
|
# |
317
|
|
|
|
|
|
|
unless ($this->{PseudoTabs}) { |
318
|
|
|
|
|
|
|
$this->{PseudoTabs} = [ undef ]; |
319
|
|
|
|
|
|
|
push @{$this->{PseudoTabs}}, $this->PseudoCreate($_) |
320
|
|
|
|
|
|
|
foreach (1..DTF_MAX_ROWS); |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
# |
323
|
|
|
|
|
|
|
# create default colors |
324
|
|
|
|
|
|
|
# |
325
|
|
|
|
|
|
|
$this->configure(-tabcolor => |
326
|
|
|
|
|
|
|
$this->Darken($this->cget(-background), 75)) |
327
|
|
|
|
|
|
|
unless $this->cget(-tabcolor); |
328
|
|
|
|
|
|
|
$this->configure(-raisecolor => |
329
|
|
|
|
|
|
|
$this->Darken($this->cget(-tabcolor), 130)) |
330
|
|
|
|
|
|
|
unless $this->cget(-raisecolor); |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
$RaiseColor = $Color ? $this->Darken($Color, 130) : |
333
|
|
|
|
|
|
|
$this->cget(-raisecolor) |
334
|
|
|
|
|
|
|
unless $RaiseColor; |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
$Color = $this->cget(-tabcolor) |
337
|
|
|
|
|
|
|
unless $Color; |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
$RaiseCmd = $this->cget(-raisecmd) |
340
|
|
|
|
|
|
|
unless $RaiseCmd; |
341
|
|
|
|
|
|
|
# |
342
|
|
|
|
|
|
|
# create a new frame for the caller |
343
|
|
|
|
|
|
|
# |
344
|
|
|
|
|
|
|
my $Widget = $this->{ClientFrame}->Frame( |
345
|
|
|
|
|
|
|
-borderwidth => $this->cget ('-borderwidth'), |
346
|
|
|
|
|
|
|
-relief => 'raised'); |
347
|
|
|
|
|
|
|
# |
348
|
|
|
|
|
|
|
# create a new frame for a tab |
349
|
|
|
|
|
|
|
# |
350
|
|
|
|
|
|
|
my $TabFrame = $ButtonFrame->Component( |
351
|
|
|
|
|
|
|
'Frame' => 'Button_'.$Widget, |
352
|
|
|
|
|
|
|
-foreground => $this->cget ('-foreground'), |
353
|
|
|
|
|
|
|
-relief => 'flat', |
354
|
|
|
|
|
|
|
-borderwidth => 0, |
355
|
|
|
|
|
|
|
); |
356
|
|
|
|
|
|
|
$TabFrame->configure(-bg => $Color) |
357
|
|
|
|
|
|
|
if $Color; |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
my $to = $taborient{$this->{Side}}; |
360
|
|
|
|
|
|
|
# |
361
|
|
|
|
|
|
|
# build a close tab for it if requested |
362
|
|
|
|
|
|
|
# |
363
|
|
|
|
|
|
|
my $CloseBtn; |
364
|
|
|
|
|
|
|
$CloseBtn = $TabFrame->Component( |
365
|
|
|
|
|
|
|
'Button' => 'CloseBtn', |
366
|
|
|
|
|
|
|
-command => [ $this->{Close}, $this, $Caption ], |
367
|
|
|
|
|
|
|
-anchor => $to->[DTF_ORIENT_CLOSEANCHOR], |
368
|
|
|
|
|
|
|
-relief => 'raised', |
369
|
|
|
|
|
|
|
-borderwidth => 1, |
370
|
|
|
|
|
|
|
-takefocus => 1, |
371
|
|
|
|
|
|
|
-padx => 0, |
372
|
|
|
|
|
|
|
-pady => 0, |
373
|
|
|
|
|
|
|
-image => $this->{CloseImage} |
374
|
|
|
|
|
|
|
) |
375
|
|
|
|
|
|
|
if $this->{Close}; |
376
|
|
|
|
|
|
|
# |
377
|
|
|
|
|
|
|
# build the tab for it; in future we may support images |
378
|
|
|
|
|
|
|
# |
379
|
|
|
|
|
|
|
my $font = $this->cget(-font); |
380
|
|
|
|
|
|
|
$font = $this->parent()->cget(-font) unless $font; |
381
|
|
|
|
|
|
|
my $padx = $this->cget(-tabpadx); |
382
|
|
|
|
|
|
|
my $pady = $this->cget(-tabpady); |
383
|
|
|
|
|
|
|
my $Button = $TabFrame->Component( |
384
|
|
|
|
|
|
|
'Button' => 'Button', |
385
|
|
|
|
|
|
|
-command => sub { $this->configure (-current => $Widget);}, |
386
|
|
|
|
|
|
|
-anchor => 'center', |
387
|
|
|
|
|
|
|
-relief => 'flat', |
388
|
|
|
|
|
|
|
-borderwidth => 0, |
389
|
|
|
|
|
|
|
-takefocus => 1, |
390
|
|
|
|
|
|
|
-padx => 1, |
391
|
|
|
|
|
|
|
-pady => 1, |
392
|
|
|
|
|
|
|
); |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
$Button->configure(-bg => $Color); |
395
|
|
|
|
|
|
|
if (defined($Image)) { |
396
|
|
|
|
|
|
|
$Button->configure(-image => $Image); |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
else { |
399
|
|
|
|
|
|
|
$Button->configure(-font => $font) if $font; |
400
|
|
|
|
|
|
|
$Text = $Caption ||= $Widget->name() |
401
|
|
|
|
|
|
|
unless $Text; |
402
|
|
|
|
|
|
|
# |
403
|
|
|
|
|
|
|
# make it vertical for side tabs |
404
|
|
|
|
|
|
|
# |
405
|
|
|
|
|
|
|
$Button->configure(-text => |
406
|
|
|
|
|
|
|
($this->cget(-textalign) ? |
407
|
|
|
|
|
|
|
($to->[DTF_ORIENT_DIRECTION] ? $Text : RotateTabText($Text)) : |
408
|
|
|
|
|
|
|
($to->[DTF_ORIENT_DIRECTION] ? RotateTabText($Text) : $Text)) |
409
|
|
|
|
|
|
|
); |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
$TabFrame->bind('' => sub {$Button->invoke();}); |
413
|
|
|
|
|
|
|
# |
414
|
|
|
|
|
|
|
# someday we'll have to figure out how to configure these |
415
|
|
|
|
|
|
|
# events so rolling into a tab brightens and roling out |
416
|
|
|
|
|
|
|
# darkens...wo/ repeating the event ad nauseum... |
417
|
|
|
|
|
|
|
# |
418
|
|
|
|
|
|
|
# $TabFrame->bind('', [ \&OnEnter, $Button, $TabFrame ]); |
419
|
|
|
|
|
|
|
# $TabFrame->bind('', [ \&OnLeave, $Button, $TabFrame ]); |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
# $Button->bind('', [ \&OnEnter, $Button, $TabFrame ]); |
422
|
|
|
|
|
|
|
# $Button->bind('', [ \&OnLeave, $Button, $TabFrame ]); |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
# $Button->bind('', [ \&OnFocusOut, $TabFrame ]); |
425
|
|
|
|
|
|
|
# $Button->bind('', [ \&OnFocusIn, $TabFrame ]); |
426
|
|
|
|
|
|
|
$Button->bind('', |
427
|
|
|
|
|
|
|
sub {($this->children())[0]->focus();}); |
428
|
|
|
|
|
|
|
$Button->bind ('' => sub {$Button->invoke();}); |
429
|
|
|
|
|
|
|
# |
430
|
|
|
|
|
|
|
# decorate the tab |
431
|
|
|
|
|
|
|
# |
432
|
|
|
|
|
|
|
$this->TabBorder ($TabFrame); |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
my $dark = $Button->Darken($Color, 50); |
435
|
|
|
|
|
|
|
$Button->configure(-highlightthickness => 0, |
436
|
|
|
|
|
|
|
-activebackground => $dark); |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
$CloseBtn->pack( |
439
|
|
|
|
|
|
|
-side => $to->[DTF_ORIENT_CLOSESIDE], |
440
|
|
|
|
|
|
|
-anchor => $to->[DTF_ORIENT_CLOSEANCHOR], |
441
|
|
|
|
|
|
|
-expand => 0, |
442
|
|
|
|
|
|
|
-fill => 'none', |
443
|
|
|
|
|
|
|
-ipadx => 0, |
444
|
|
|
|
|
|
|
-ipady => 0, |
445
|
|
|
|
|
|
|
-padx => 2, |
446
|
|
|
|
|
|
|
-pady => 2, |
447
|
|
|
|
|
|
|
) |
448
|
|
|
|
|
|
|
if $CloseBtn; |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
$Button->pack( |
451
|
|
|
|
|
|
|
-side => $to->[DTF_ORIENT_BTNSIDE], |
452
|
|
|
|
|
|
|
-anchor => $to->[DTF_ORIENT_BTNANCHOR], |
453
|
|
|
|
|
|
|
-expand => 0, |
454
|
|
|
|
|
|
|
-fill => 'none', |
455
|
|
|
|
|
|
|
-ipadx => 0, |
456
|
|
|
|
|
|
|
-ipady => 0, |
457
|
|
|
|
|
|
|
-padx => $padx, |
458
|
|
|
|
|
|
|
-pady => $pady, |
459
|
|
|
|
|
|
|
); |
460
|
|
|
|
|
|
|
# |
461
|
|
|
|
|
|
|
# pack tab in our rowframe 0; redraw if needed |
462
|
|
|
|
|
|
|
# move everything over 1 column in bottom row |
463
|
|
|
|
|
|
|
# |
464
|
|
|
|
|
|
|
$clients->[$_][DTF_IDX_COL]++ |
465
|
|
|
|
|
|
|
foreach (@{$rows->[0]}); |
466
|
|
|
|
|
|
|
unshift @{$rows->[0]}, scalar @$clients; |
467
|
|
|
|
|
|
|
# |
468
|
|
|
|
|
|
|
# save the client frame, the caption, the tabcolor, |
469
|
|
|
|
|
|
|
# the current row/column coords of our tab, our tabframe, |
470
|
|
|
|
|
|
|
# and the original height of this tab; we'll be stretching |
471
|
|
|
|
|
|
|
# the button later during redraws |
472
|
|
|
|
|
|
|
# |
473
|
|
|
|
|
|
|
push @$clients, [ |
474
|
|
|
|
|
|
|
$Widget, # our client frame |
475
|
|
|
|
|
|
|
$Caption, # our identifier |
476
|
|
|
|
|
|
|
$Color, # unraised color |
477
|
|
|
|
|
|
|
0, # row number |
478
|
|
|
|
|
|
|
0, # column number |
479
|
|
|
|
|
|
|
$TabFrame, # our tab frame |
480
|
|
|
|
|
|
|
($to->[DTF_ORIENT_DIRECTION] ? # the tab width |
481
|
|
|
|
|
|
|
$Button->reqwidth() : $Button->reqheight() ), |
482
|
|
|
|
|
|
|
($to->[DTF_ORIENT_DIRECTION] ? # the tab height |
483
|
|
|
|
|
|
|
$Button->reqheight() : $Button->reqwidth() ), |
484
|
|
|
|
|
|
|
$RaiseColor, # raised color |
485
|
|
|
|
|
|
|
$RaiseCmd, # callback for raise operations |
486
|
|
|
|
|
|
|
$Text, # tab label text |
487
|
|
|
|
|
|
|
1 # start as visible |
488
|
|
|
|
|
|
|
]; |
489
|
|
|
|
|
|
|
# |
490
|
|
|
|
|
|
|
# reqwidht/height don't seem to include the padx/pady |
491
|
|
|
|
|
|
|
# |
492
|
|
|
|
|
|
|
$$clients[-1][DTF_IDX_HEIGHT] += (2 * |
493
|
|
|
|
|
|
|
($to->[DTF_ORIENT_DIRECTION] ? $pady : $padx)); |
494
|
|
|
|
|
|
|
$$clients[-1][DTF_IDX_WIDTH] += (2 * |
495
|
|
|
|
|
|
|
($to->[DTF_ORIENT_DIRECTION] ? $padx : $pady)); |
496
|
|
|
|
|
|
|
# |
497
|
|
|
|
|
|
|
# map the caption to its position in the client list, |
498
|
|
|
|
|
|
|
# so we can raise and delete it by reference |
499
|
|
|
|
|
|
|
# |
500
|
|
|
|
|
|
|
$this->{ClientHash}{$Caption} = $#$clients; |
501
|
|
|
|
|
|
|
# |
502
|
|
|
|
|
|
|
# redraw everything |
503
|
|
|
|
|
|
|
# |
504
|
|
|
|
|
|
|
$this->TabRedraw(1); |
505
|
|
|
|
|
|
|
# |
506
|
|
|
|
|
|
|
# and raise us |
507
|
|
|
|
|
|
|
# |
508
|
|
|
|
|
|
|
$this->TabRaise($Widget); |
509
|
|
|
|
|
|
|
return $Widget; |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
sub PseudoCreate { |
513
|
|
|
|
|
|
|
my ($this, $row) = @_; |
514
|
|
|
|
|
|
|
# |
515
|
|
|
|
|
|
|
# create a new frame for a pseudotab |
516
|
|
|
|
|
|
|
# |
517
|
|
|
|
|
|
|
my $TabFrame = $this->{ButtonFrame}->Component( |
518
|
|
|
|
|
|
|
'Frame' => "Pseudo_$row", |
519
|
|
|
|
|
|
|
-foreground => $this->cget ('-foreground'), |
520
|
|
|
|
|
|
|
-relief => 'flat', |
521
|
|
|
|
|
|
|
-borderwidth => 0, |
522
|
|
|
|
|
|
|
); |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
$TabFrame->Component( |
525
|
|
|
|
|
|
|
'Label' => 'Button', |
526
|
|
|
|
|
|
|
-text => ' ', |
527
|
|
|
|
|
|
|
-anchor => $taborient{$this->{Side}}[DTF_ORIENT_PSEUDOANCHOR], |
528
|
|
|
|
|
|
|
-relief => 'flat', |
529
|
|
|
|
|
|
|
-borderwidth => 0, |
530
|
|
|
|
|
|
|
-padx => 2, |
531
|
|
|
|
|
|
|
-pady => 2, |
532
|
|
|
|
|
|
|
)->pack( |
533
|
|
|
|
|
|
|
-expand => 0, |
534
|
|
|
|
|
|
|
-fill => 'both', |
535
|
|
|
|
|
|
|
-ipadx => 0, |
536
|
|
|
|
|
|
|
-ipady => 0, |
537
|
|
|
|
|
|
|
-padx => 3, |
538
|
|
|
|
|
|
|
-pady => 3, |
539
|
|
|
|
|
|
|
); |
540
|
|
|
|
|
|
|
# |
541
|
|
|
|
|
|
|
# decorate the tab |
542
|
|
|
|
|
|
|
# |
543
|
|
|
|
|
|
|
$this->TabBorder ($TabFrame, 1); |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
return $TabFrame; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
sub TabRaise { |
549
|
|
|
|
|
|
|
my ($this, $Widget, $silent) = (shift, @_); |
550
|
|
|
|
|
|
|
# |
551
|
|
|
|
|
|
|
# locate the tab row |
552
|
|
|
|
|
|
|
# if its not the first row, then we need to move rows around |
553
|
|
|
|
|
|
|
# and redraw |
554
|
|
|
|
|
|
|
# else just raise it |
555
|
|
|
|
|
|
|
# |
556
|
|
|
|
|
|
|
my $ButtonFrame = $this->{ButtonFrame}; |
557
|
|
|
|
|
|
|
my $TabFrame = $ButtonFrame->Subwidget('Button_'.$Widget); |
558
|
|
|
|
|
|
|
my $rotate = $this->cget(-tabrotate); |
559
|
|
|
|
|
|
|
# |
560
|
|
|
|
|
|
|
# find our client |
561
|
|
|
|
|
|
|
# |
562
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
563
|
|
|
|
|
|
|
# |
564
|
|
|
|
|
|
|
# strange timing issue sometimes leaves a null |
565
|
|
|
|
|
|
|
# entry at our tail |
566
|
|
|
|
|
|
|
# |
567
|
|
|
|
|
|
|
pop @$clients unless defined($clients->[-1]); |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
my $client; |
570
|
|
|
|
|
|
|
# |
571
|
|
|
|
|
|
|
# locate the currently raised tab and restore its |
572
|
|
|
|
|
|
|
# unraised color |
573
|
|
|
|
|
|
|
# |
574
|
|
|
|
|
|
|
foreach $client (@$clients) { |
575
|
|
|
|
|
|
|
last unless $this->{Raised}; |
576
|
|
|
|
|
|
|
next unless ($client->[DTF_IDX_WIDGET] eq $this->{Raised}); |
577
|
|
|
|
|
|
|
my $Button = $client->[DTF_IDX_FRAME]->Subwidget('Button'); |
578
|
|
|
|
|
|
|
$client->[DTF_IDX_FRAME]->configure(-bg => $client->[DTF_IDX_COLOR]); |
579
|
|
|
|
|
|
|
$Button->configure(-bg => $client->[DTF_IDX_COLOR], |
580
|
|
|
|
|
|
|
-activebackground => $client->[DTF_IDX_COLOR], |
581
|
|
|
|
|
|
|
); |
582
|
|
|
|
|
|
|
last; |
583
|
|
|
|
|
|
|
} |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
my $raised = 0; |
586
|
|
|
|
|
|
|
$raised++ |
587
|
|
|
|
|
|
|
while (($raised <= $#$clients) && |
588
|
|
|
|
|
|
|
($clients->[$raised][DTF_IDX_WIDGET] ne $Widget)); |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
return 1 unless ($raised <= $#$clients); |
591
|
|
|
|
|
|
|
$client = $clients->[$raised]; |
592
|
|
|
|
|
|
|
my ($r, $c) = ($client->[DTF_IDX_ROW], $client->[DTF_IDX_COL]); |
593
|
|
|
|
|
|
|
my $rows = $this->{RowList}; |
594
|
|
|
|
|
|
|
# |
595
|
|
|
|
|
|
|
# undraw the Connector |
596
|
|
|
|
|
|
|
# |
597
|
|
|
|
|
|
|
my $Connector = $this->Subwidget('Connector'); |
598
|
|
|
|
|
|
|
$Connector->placeForget(); # if $Connector->is_mapped; |
599
|
|
|
|
|
|
|
delete $this->{Raised}; |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
if ($rotate) { |
602
|
|
|
|
|
|
|
# |
603
|
|
|
|
|
|
|
# 3 cases: |
604
|
|
|
|
|
|
|
# we're already at row 0, so just raise |
605
|
|
|
|
|
|
|
# else rotate rows off bottom to top until |
606
|
|
|
|
|
|
|
# raised row is bottom row |
607
|
|
|
|
|
|
|
# |
608
|
|
|
|
|
|
|
if ($r != 0) { |
609
|
|
|
|
|
|
|
# |
610
|
|
|
|
|
|
|
# middle row, or last row that fills the frame: |
611
|
|
|
|
|
|
|
# move the preceding to top, and move the selected row |
612
|
|
|
|
|
|
|
# to the bottom |
613
|
|
|
|
|
|
|
# |
614
|
|
|
|
|
|
|
my $rowcnt = $r; |
615
|
|
|
|
|
|
|
push(@$rows, (shift @$rows)), |
616
|
|
|
|
|
|
|
$rowcnt-- |
617
|
|
|
|
|
|
|
while ($rowcnt); |
618
|
|
|
|
|
|
|
# |
619
|
|
|
|
|
|
|
# update client coords |
620
|
|
|
|
|
|
|
# |
621
|
|
|
|
|
|
|
foreach my $i (0..$#$rows) { |
622
|
|
|
|
|
|
|
$clients->[$_][DTF_IDX_ROW] = $i |
623
|
|
|
|
|
|
|
foreach (@{$rows->[$i]}); |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
$this->TabRedraw; |
626
|
|
|
|
|
|
|
} |
627
|
|
|
|
|
|
|
# |
628
|
|
|
|
|
|
|
# first, lower everything below the raised tab |
629
|
|
|
|
|
|
|
# in row 0 |
630
|
|
|
|
|
|
|
# |
631
|
|
|
|
|
|
|
my $lowest = $raised; |
632
|
|
|
|
|
|
|
my $pseudos = $this->{PseudoTabs}; |
633
|
|
|
|
|
|
|
foreach (@{$rows->[0]}) { |
634
|
|
|
|
|
|
|
$clients->[$_][DTF_IDX_FRAME]->lower($clients->[$lowest][DTF_IDX_FRAME]), |
635
|
|
|
|
|
|
|
$lowest = $_ |
636
|
|
|
|
|
|
|
unless ($_ == $raised); |
637
|
|
|
|
|
|
|
} |
638
|
|
|
|
|
|
|
# |
639
|
|
|
|
|
|
|
# now lower everything below its left neighbor |
640
|
|
|
|
|
|
|
# |
641
|
|
|
|
|
|
|
foreach my $i (1..$#$rows) { |
642
|
|
|
|
|
|
|
$clients->[$_][DTF_IDX_FRAME]->lower($clients->[$lowest][DTF_IDX_FRAME]), |
643
|
|
|
|
|
|
|
$lowest = $_ |
644
|
|
|
|
|
|
|
foreach (@{$rows->[$i]}); |
645
|
|
|
|
|
|
|
} |
646
|
|
|
|
|
|
|
# |
647
|
|
|
|
|
|
|
# now make all pseudos lower |
648
|
|
|
|
|
|
|
# |
649
|
|
|
|
|
|
|
if ($#$rows > 0) { |
650
|
|
|
|
|
|
|
$pseudos->[1]->lower($clients->[$lowest][DTF_IDX_FRAME]); |
651
|
|
|
|
|
|
|
$pseudos->[$_]->lower($pseudos->[$_-1]) |
652
|
|
|
|
|
|
|
foreach (2..$#$rows); |
653
|
|
|
|
|
|
|
} |
654
|
|
|
|
|
|
|
$TabFrame->Subwidget('Button')->raise(); |
655
|
|
|
|
|
|
|
$TabFrame->raise(); |
656
|
|
|
|
|
|
|
} # if rotate |
657
|
|
|
|
|
|
|
$TabFrame->Subwidget('Button')->focus(); |
658
|
|
|
|
|
|
|
# |
659
|
|
|
|
|
|
|
# lower the current frame, and then raise the new one |
660
|
|
|
|
|
|
|
# !!!NOTE: we can't use pack() here, as it tends to |
661
|
|
|
|
|
|
|
# expand the area of our container |
662
|
|
|
|
|
|
|
# |
663
|
|
|
|
|
|
|
$Widget->place(-x => 0, -y => 0, -relheight => 1.0, -relwidth => 1.0); |
664
|
|
|
|
|
|
|
$this->{CurrentFrame} = $Widget; |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
pop @$clients unless defined($clients->[-1]); |
667
|
|
|
|
|
|
|
foreach (0..$#$clients) { |
668
|
|
|
|
|
|
|
$clients->[$_][DTF_IDX_WIDGET]->lower($Widget) |
669
|
|
|
|
|
|
|
if ($clients->[$_] && $clients->[$_][DTF_IDX_WIDGET] && |
670
|
|
|
|
|
|
|
($clients->[$_][DTF_IDX_WIDGET] ne $Widget)); |
671
|
|
|
|
|
|
|
} |
672
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
my $raisecolor = $client->[DTF_IDX_RAISECOLOR]; |
674
|
|
|
|
|
|
|
# |
675
|
|
|
|
|
|
|
# used to smoothly connect raised tab to client frame |
676
|
|
|
|
|
|
|
# but only if in row 0 |
677
|
|
|
|
|
|
|
# |
678
|
|
|
|
|
|
|
if ($client->[DTF_IDX_ROW] == 0) { |
679
|
|
|
|
|
|
|
$this->update; # make sure the tabs are redrawn |
680
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
my ($connectx, $connectw, $connecty, $connecth); |
682
|
|
|
|
|
|
|
my $horizontal = $taborient{$this->{Side}}[DTF_ORIENT_DIRECTION]; |
683
|
|
|
|
|
|
|
my $inside = $taborient{$this->{Side}}[DTF_ORIENT_ALIGN]; |
684
|
|
|
|
|
|
|
my $extra = $this->{Close} ? 12 : -3; |
685
|
|
|
|
|
|
|
if ($horizontal) { # |
686
|
|
|
|
|
|
|
$connectx = $TabFrame->x + 2; |
687
|
|
|
|
|
|
|
$connectw = $client->[DTF_IDX_WIDTH] + $extra; |
688
|
|
|
|
|
|
|
# |
689
|
|
|
|
|
|
|
# Y location of connector is either at top (for nw/ne) |
690
|
|
|
|
|
|
|
# or bottom (for sw/se) of the client frame |
691
|
|
|
|
|
|
|
# |
692
|
|
|
|
|
|
|
$connecty = $inside ? |
693
|
|
|
|
|
|
|
$this->{ClientFrame}->height() - 2 : # may need to adjust this offset |
694
|
|
|
|
|
|
|
$this->{ClientFrame}->rooty() - $this->rooty() - 7; |
695
|
|
|
|
|
|
|
$connecth = $this->{ClientFrame}->cget(-borderwidth) + 3; |
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
else { # vertical |
698
|
|
|
|
|
|
|
# |
699
|
|
|
|
|
|
|
# if tabs at left, then position at left edge of client |
700
|
|
|
|
|
|
|
# else position at rt edge |
701
|
|
|
|
|
|
|
# |
702
|
|
|
|
|
|
|
$connectx = $inside ? |
703
|
|
|
|
|
|
|
$this->{ClientFrame}->rootx() - $this->rootx() - 8 : |
704
|
|
|
|
|
|
|
$this->{ClientFrame}->width() - 3; # may need to adjust this offset |
705
|
|
|
|
|
|
|
$connectw = $this->{ClientFrame}->cget(-borderwidth) + 3; |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
$connecty = $TabFrame->y + 3; |
708
|
|
|
|
|
|
|
$connecth = $client->[DTF_IDX_WIDTH] + $extra; |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
$Connector->place( |
711
|
|
|
|
|
|
|
-x => $connectx, |
712
|
|
|
|
|
|
|
-y => $connecty, |
713
|
|
|
|
|
|
|
-height => $connecth, |
714
|
|
|
|
|
|
|
-width => $connectw, |
715
|
|
|
|
|
|
|
-anchor => 'nw', |
716
|
|
|
|
|
|
|
); |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
$Connector->configure(-background => $raisecolor); |
719
|
|
|
|
|
|
|
$Connector->raise(); |
720
|
|
|
|
|
|
|
} # end if raise in row 0 |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
$this->{Raised} = $Widget; |
723
|
|
|
|
|
|
|
# |
724
|
|
|
|
|
|
|
# turn off flashing |
725
|
|
|
|
|
|
|
# |
726
|
|
|
|
|
|
|
$this->deflash($client->[DTF_IDX_CAPTION]) |
727
|
|
|
|
|
|
|
if $client->[DTF_IDX_FLASH_ID]; |
728
|
|
|
|
|
|
|
# |
729
|
|
|
|
|
|
|
# set raised color |
730
|
|
|
|
|
|
|
# |
731
|
|
|
|
|
|
|
$TabFrame->configure(-background => $raisecolor), |
732
|
|
|
|
|
|
|
$TabFrame->Subwidget('Button')->configure( |
733
|
|
|
|
|
|
|
-bg => $raisecolor, |
734
|
|
|
|
|
|
|
-activebackground => $raisecolor); |
735
|
|
|
|
|
|
|
# |
736
|
|
|
|
|
|
|
# callback if defined && allowed |
737
|
|
|
|
|
|
|
# |
738
|
|
|
|
|
|
|
unless ($silent) { |
739
|
|
|
|
|
|
|
my $raisecb = $client->[DTF_IDX_RAISECMD]; |
740
|
|
|
|
|
|
|
&$raisecb($client->[DTF_IDX_CAPTION]) |
741
|
|
|
|
|
|
|
if ($raisecb && (ref $raisecb) && (ref $raisecb eq 'CODE')); |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
return $Widget; |
744
|
|
|
|
|
|
|
} |
745
|
|
|
|
|
|
|
# |
746
|
|
|
|
|
|
|
# render tab borders |
747
|
|
|
|
|
|
|
# |
748
|
|
|
|
|
|
|
sub TabBorder { |
749
|
|
|
|
|
|
|
my ($this, $TabFrame, $forpseudo) = @_; |
750
|
|
|
|
|
|
|
my $LineWidth = $this->cget(-borderwidth); |
751
|
|
|
|
|
|
|
my $Background = $this->cget(-background); |
752
|
|
|
|
|
|
|
my $InnerBackground = $TabFrame->Darken($Background, 120), |
753
|
|
|
|
|
|
|
my $Curve = $this->cget (-tabcurve); |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
my $mask = $forpseudo ? $borders{'p' . $this->{Side}} : |
756
|
|
|
|
|
|
|
$borders{$this->{Side}}; |
757
|
|
|
|
|
|
|
# |
758
|
|
|
|
|
|
|
# left border |
759
|
|
|
|
|
|
|
# outer: |
760
|
|
|
|
|
|
|
$TabFrame->Frame( |
761
|
|
|
|
|
|
|
-background => 'white', |
762
|
|
|
|
|
|
|
-borderwidth => 0, |
763
|
|
|
|
|
|
|
)->place( |
764
|
|
|
|
|
|
|
-x => 0, |
765
|
|
|
|
|
|
|
-y => $Curve - 1, |
766
|
|
|
|
|
|
|
-width => $LineWidth, |
767
|
|
|
|
|
|
|
-relheight => 1.0, |
768
|
|
|
|
|
|
|
), |
769
|
|
|
|
|
|
|
# |
770
|
|
|
|
|
|
|
# inner: |
771
|
|
|
|
|
|
|
$TabFrame->Frame( |
772
|
|
|
|
|
|
|
-background => $InnerBackground, |
773
|
|
|
|
|
|
|
-borderwidth => 0, |
774
|
|
|
|
|
|
|
)->place( |
775
|
|
|
|
|
|
|
-x => $LineWidth, |
776
|
|
|
|
|
|
|
-y => $Curve - 1, |
777
|
|
|
|
|
|
|
-width => $LineWidth, |
778
|
|
|
|
|
|
|
-relheight => 1.0, |
779
|
|
|
|
|
|
|
) |
780
|
|
|
|
|
|
|
if ($mask & 1); |
781
|
|
|
|
|
|
|
# |
782
|
|
|
|
|
|
|
# right border |
783
|
|
|
|
|
|
|
# outer: |
784
|
|
|
|
|
|
|
$TabFrame->Frame( |
785
|
|
|
|
|
|
|
-background => 'black', |
786
|
|
|
|
|
|
|
-borderwidth => 0, |
787
|
|
|
|
|
|
|
)->place( |
788
|
|
|
|
|
|
|
-x => - ($LineWidth), |
789
|
|
|
|
|
|
|
-relx => 1.0, |
790
|
|
|
|
|
|
|
-width => $LineWidth, |
791
|
|
|
|
|
|
|
-relheight => 1.0, |
792
|
|
|
|
|
|
|
-y => $Curve, |
793
|
|
|
|
|
|
|
), |
794
|
|
|
|
|
|
|
# |
795
|
|
|
|
|
|
|
# inner: |
796
|
|
|
|
|
|
|
$TabFrame->Frame( |
797
|
|
|
|
|
|
|
-background => $TabFrame->Darken($Background, 80), |
798
|
|
|
|
|
|
|
-borderwidth => 0, |
799
|
|
|
|
|
|
|
)->place( |
800
|
|
|
|
|
|
|
-x => - ($LineWidth * 2), |
801
|
|
|
|
|
|
|
-width => $LineWidth, |
802
|
|
|
|
|
|
|
-relheight => 1.0, |
803
|
|
|
|
|
|
|
-y => $Curve / 2, |
804
|
|
|
|
|
|
|
-relx => 1.0, |
805
|
|
|
|
|
|
|
) |
806
|
|
|
|
|
|
|
if ($mask & 2); |
807
|
|
|
|
|
|
|
# |
808
|
|
|
|
|
|
|
# top border |
809
|
|
|
|
|
|
|
# outer: |
810
|
|
|
|
|
|
|
$TabFrame->Frame( |
811
|
|
|
|
|
|
|
-background => 'white', |
812
|
|
|
|
|
|
|
-borderwidth => 0, |
813
|
|
|
|
|
|
|
)->place( |
814
|
|
|
|
|
|
|
-x => $Curve - 1, |
815
|
|
|
|
|
|
|
-y => 0, |
816
|
|
|
|
|
|
|
-relwidth => 1.0, |
817
|
|
|
|
|
|
|
-height => $LineWidth, |
818
|
|
|
|
|
|
|
-width => - ($Curve * 2), |
819
|
|
|
|
|
|
|
), |
820
|
|
|
|
|
|
|
# |
821
|
|
|
|
|
|
|
# inner: |
822
|
|
|
|
|
|
|
$TabFrame->Frame( |
823
|
|
|
|
|
|
|
-background => $InnerBackground, |
824
|
|
|
|
|
|
|
-borderwidth => 0, |
825
|
|
|
|
|
|
|
)->place( |
826
|
|
|
|
|
|
|
-x => $Curve - 1, |
827
|
|
|
|
|
|
|
-y => $LineWidth, |
828
|
|
|
|
|
|
|
-relwidth => 1.0, |
829
|
|
|
|
|
|
|
-height => $LineWidth, |
830
|
|
|
|
|
|
|
-width => - ($Curve * 2), |
831
|
|
|
|
|
|
|
) |
832
|
|
|
|
|
|
|
if ($mask & 4); |
833
|
|
|
|
|
|
|
# |
834
|
|
|
|
|
|
|
# bottom border |
835
|
|
|
|
|
|
|
# outer: |
836
|
|
|
|
|
|
|
$TabFrame->Frame( |
837
|
|
|
|
|
|
|
-background => $InnerBackground, |
838
|
|
|
|
|
|
|
-borderwidth => 0, |
839
|
|
|
|
|
|
|
)->place( |
840
|
|
|
|
|
|
|
-x => $Curve - 1, |
841
|
|
|
|
|
|
|
# -y => - ($LineWidth), |
842
|
|
|
|
|
|
|
-rely => 1.0, |
843
|
|
|
|
|
|
|
-relwidth => 1.0, |
844
|
|
|
|
|
|
|
-height => $LineWidth, |
845
|
|
|
|
|
|
|
-width => - ($Curve), |
846
|
|
|
|
|
|
|
), |
847
|
|
|
|
|
|
|
# |
848
|
|
|
|
|
|
|
# inner: |
849
|
|
|
|
|
|
|
$TabFrame->Frame( |
850
|
|
|
|
|
|
|
-background => 'black', |
851
|
|
|
|
|
|
|
-borderwidth => 0, |
852
|
|
|
|
|
|
|
-height => $LineWidth, |
853
|
|
|
|
|
|
|
)->place( |
854
|
|
|
|
|
|
|
-x => $Curve - 1, |
855
|
|
|
|
|
|
|
-y => - ($LineWidth), |
856
|
|
|
|
|
|
|
-rely => 1.0, |
857
|
|
|
|
|
|
|
-relwidth => 1.0, |
858
|
|
|
|
|
|
|
-height => $LineWidth, |
859
|
|
|
|
|
|
|
-width => - ($Curve), |
860
|
|
|
|
|
|
|
) |
861
|
|
|
|
|
|
|
if ($mask & 8); |
862
|
|
|
|
|
|
|
} |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
sub TabCurrent { |
865
|
|
|
|
|
|
|
return defined ($_[1]) ? |
866
|
|
|
|
|
|
|
$_[0]->TabRaise($_[1]) : |
867
|
|
|
|
|
|
|
$_[0]{Raised}; |
868
|
|
|
|
|
|
|
} |
869
|
|
|
|
|
|
|
# |
870
|
|
|
|
|
|
|
# returns the width of a row |
871
|
|
|
|
|
|
|
# |
872
|
|
|
|
|
|
|
sub GetButtonRowWidth { |
873
|
|
|
|
|
|
|
my ($Width, $this, $row) = (0, shift, shift); |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
return 0 |
876
|
|
|
|
|
|
|
unless ($this->{RowList} && ($#{$this->{RowList}} >= $row)); |
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
my $rowlist = $this->{RowList}[$row]; |
879
|
|
|
|
|
|
|
my $tablist = $this->{ClientList}; |
880
|
|
|
|
|
|
|
my $extra = 5 + ($this->{Close} ? 15 : 0); |
881
|
|
|
|
|
|
|
my $horizontal = $taborient{$this->{Side}}[DTF_ORIENT_DIRECTION]; |
882
|
|
|
|
|
|
|
foreach my $Client (@$rowlist) { |
883
|
|
|
|
|
|
|
$Width += $extra + ($tablist->[$Client][DTF_IDX_WIDTH]) |
884
|
|
|
|
|
|
|
if defined($tablist->[$Client]); |
885
|
|
|
|
|
|
|
} |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
return $Width ? $Width - 10 : 0; |
888
|
|
|
|
|
|
|
} |
889
|
|
|
|
|
|
|
# |
890
|
|
|
|
|
|
|
# returns the accumulated height of all our rows |
891
|
|
|
|
|
|
|
# |
892
|
|
|
|
|
|
|
sub GetButtonRowHeight { |
893
|
|
|
|
|
|
|
my ($Height, $this, $row) = (0, shift, shift); |
894
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
return 0 |
896
|
|
|
|
|
|
|
unless ($this->{RowList} && ($#{$this->{RowList}} >= $row)); |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
my $total_ht = 0; |
899
|
|
|
|
|
|
|
$total_ht += $this->GetRowHeight($_) |
900
|
|
|
|
|
|
|
foreach (0..$row); |
901
|
|
|
|
|
|
|
return $total_ht; |
902
|
|
|
|
|
|
|
} |
903
|
|
|
|
|
|
|
# |
904
|
|
|
|
|
|
|
# returns the height of a single row |
905
|
|
|
|
|
|
|
# |
906
|
|
|
|
|
|
|
sub GetRowHeight { |
907
|
|
|
|
|
|
|
my ($Height, $this, $row) = (0, shift, shift); |
908
|
|
|
|
|
|
|
my $ButtonFrame = $this->{ButtonFrame}; |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
return 0 |
911
|
|
|
|
|
|
|
unless ($this->{RowList} && ($#{$this->{RowList}} >= $row)); |
912
|
|
|
|
|
|
|
|
913
|
|
|
|
|
|
|
my $rowlist = $this->{RowList}[$row]; |
914
|
|
|
|
|
|
|
my $tablist = $this->{ClientList}; |
915
|
|
|
|
|
|
|
my $total_ht = 0; |
916
|
|
|
|
|
|
|
my $newht = 0; |
917
|
|
|
|
|
|
|
foreach (@$rowlist) { |
918
|
|
|
|
|
|
|
next unless defined($tablist->[$_]); |
919
|
|
|
|
|
|
|
$newht = $tablist->[$_][DTF_IDX_HEIGHT]; |
920
|
|
|
|
|
|
|
$Height = $newht if ($newht > $Height); |
921
|
|
|
|
|
|
|
} |
922
|
|
|
|
|
|
|
return $Height; |
923
|
|
|
|
|
|
|
} |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
sub Font { |
926
|
|
|
|
|
|
|
my ($this, $Font) = (shift, @_); |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
my $font = $this->{Font}; |
929
|
|
|
|
|
|
|
$font = $this->parent()->cget(-font) unless $font; |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
return ($font) |
932
|
|
|
|
|
|
|
unless (defined ($Font)); |
933
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
my $tablist = $this->{ClientList}; |
935
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
$_->[DTF_IDX_FRAME]->Subwidget('Button')->configure(-font => $Font) |
937
|
|
|
|
|
|
|
foreach (@$tablist); |
938
|
|
|
|
|
|
|
# |
939
|
|
|
|
|
|
|
# we need to redraw, since this may change our tab layout |
940
|
|
|
|
|
|
|
# |
941
|
|
|
|
|
|
|
$this->TabRedraw(1); |
942
|
|
|
|
|
|
|
return ($this->{Font} = $Font); |
943
|
|
|
|
|
|
|
} |
944
|
|
|
|
|
|
|
# |
945
|
|
|
|
|
|
|
# Reconfigure the tabs on resize event |
946
|
|
|
|
|
|
|
# |
947
|
|
|
|
|
|
|
sub TabReconfig { |
948
|
|
|
|
|
|
|
my $this = shift; |
949
|
|
|
|
|
|
|
return 1 |
950
|
|
|
|
|
|
|
if ($this->{Updating} || |
951
|
|
|
|
|
|
|
($this->cget(-tablock) && (! $this->cget(-tabclose)))); |
952
|
|
|
|
|
|
|
my $buttons = $this->{ButtonFrame}; |
953
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
954
|
|
|
|
|
|
|
# |
955
|
|
|
|
|
|
|
# if nothing to draw, then just update context |
956
|
|
|
|
|
|
|
# |
957
|
|
|
|
|
|
|
$this->{OldWidth} = $this->width, |
958
|
|
|
|
|
|
|
$this->{OldHeight} = $this->height, |
959
|
|
|
|
|
|
|
return 1 |
960
|
|
|
|
|
|
|
unless ($#$clients >= 0); |
961
|
|
|
|
|
|
|
# |
962
|
|
|
|
|
|
|
# compute current max row width |
963
|
|
|
|
|
|
|
# compare to current frame width |
964
|
|
|
|
|
|
|
# if maxrow > frame |
965
|
|
|
|
|
|
|
# redraw |
966
|
|
|
|
|
|
|
# elsif maxrow - frame > threshold |
967
|
|
|
|
|
|
|
# redraw |
968
|
|
|
|
|
|
|
# |
969
|
|
|
|
|
|
|
my $rows = $this->{RowList}; |
970
|
|
|
|
|
|
|
my $w = $buttons->width(); |
971
|
|
|
|
|
|
|
my $h = $buttons->height(); |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
my $maxw = 0; |
974
|
|
|
|
|
|
|
foreach (0..$#$rows) { |
975
|
|
|
|
|
|
|
my $rw = $this->GetButtonRowWidth($_); |
976
|
|
|
|
|
|
|
$maxw = $rw if ($maxw < $rw); |
977
|
|
|
|
|
|
|
} |
978
|
|
|
|
|
|
|
# |
979
|
|
|
|
|
|
|
# return unless significantly different from old size |
980
|
|
|
|
|
|
|
# |
981
|
|
|
|
|
|
|
$this->{OldWidth} = $this->width, |
982
|
|
|
|
|
|
|
$this->{OldHeight} = $this->height, |
983
|
|
|
|
|
|
|
return 1 |
984
|
|
|
|
|
|
|
unless (($maxw > $w) || ($w - $maxw > 10)); |
985
|
|
|
|
|
|
|
# |
986
|
|
|
|
|
|
|
# just redraw everything |
987
|
|
|
|
|
|
|
# |
988
|
|
|
|
|
|
|
$this->{Updating} = 1; |
989
|
|
|
|
|
|
|
$this->TabRedraw(1); |
990
|
|
|
|
|
|
|
$this->{Updating} = undef; |
991
|
|
|
|
|
|
|
$this->{OldWidth} = $this->width; |
992
|
|
|
|
|
|
|
$this->{OldHeight} = $this->height; |
993
|
|
|
|
|
|
|
return 1; |
994
|
|
|
|
|
|
|
} |
995
|
|
|
|
|
|
|
# |
996
|
|
|
|
|
|
|
# redraw our tabs |
997
|
|
|
|
|
|
|
# |
998
|
|
|
|
|
|
|
sub TabRedraw { |
999
|
|
|
|
|
|
|
my ($this, $rearrange) = @_; |
1000
|
|
|
|
|
|
|
# |
1001
|
|
|
|
|
|
|
# compute new display ordering |
1002
|
|
|
|
|
|
|
# |
1003
|
|
|
|
|
|
|
return 1 unless ($#{$this->{ClientList}} >= 0); |
1004
|
|
|
|
|
|
|
my $ButtonFrame = $this->{ButtonFrame}; |
1005
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
1006
|
|
|
|
|
|
|
my $rows = $this->{RowList}; |
1007
|
|
|
|
|
|
|
# |
1008
|
|
|
|
|
|
|
# if nothing to draw, bail out |
1009
|
|
|
|
|
|
|
# |
1010
|
|
|
|
|
|
|
return 1 if (($#$rows < 0) || |
1011
|
|
|
|
|
|
|
(($#$rows == 0) && ($#{$rows->[0]} < 0))); |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
my $pseudos = $this->{PseudoTabs}; |
1014
|
|
|
|
|
|
|
my $pseudoht; |
1015
|
|
|
|
|
|
|
my $Raised = $this->{Raised}; # save for later |
1016
|
|
|
|
|
|
|
my $roww = 0; |
1017
|
|
|
|
|
|
|
my $raised_row = undef; |
1018
|
|
|
|
|
|
|
my $horizontal = $taborient{$this->{Side}}[DTF_ORIENT_DIRECTION]; |
1019
|
|
|
|
|
|
|
my $alignment = $taborient{$this->{Side}}[DTF_ORIENT_PSEUDOANCHOR]; |
1020
|
|
|
|
|
|
|
my $downward = $taborient{$this->{Side}}[DTF_ORIENT_DOWNWARD]; |
1021
|
|
|
|
|
|
|
my $extra = $this->{Close} ? 15 : 0; |
1022
|
|
|
|
|
|
|
# |
1023
|
|
|
|
|
|
|
# tabspace determined based on orientation |
1024
|
|
|
|
|
|
|
# |
1025
|
|
|
|
|
|
|
my $w = $horizontal ? $ButtonFrame->width() : $ButtonFrame->height(); |
1026
|
|
|
|
|
|
|
$w -= 5; |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
if ($rearrange) { |
1029
|
|
|
|
|
|
|
# |
1030
|
|
|
|
|
|
|
# rearrange tabs to fit new frame width |
1031
|
|
|
|
|
|
|
# |
1032
|
|
|
|
|
|
|
my @newrows = ([]); |
1033
|
|
|
|
|
|
|
my @tclients = (); |
1034
|
|
|
|
|
|
|
foreach my $row (@$rows) { |
1035
|
|
|
|
|
|
|
foreach (@$row) { |
1036
|
|
|
|
|
|
|
my $client = $clients->[$_]; |
1037
|
|
|
|
|
|
|
next |
1038
|
|
|
|
|
|
|
if $client->[DTF_IDX_HIDDEN]; |
1039
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
my $btnw = $extra + $client->[DTF_IDX_WIDTH]; |
1041
|
|
|
|
|
|
|
my $row = $#$rows; |
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
$roww = 0, |
1044
|
|
|
|
|
|
|
push @newrows, [ ] |
1045
|
|
|
|
|
|
|
if (($roww + $btnw > $w) && ($#{$newrows[0]} >= 0)); |
1046
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
$roww += $btnw; |
1048
|
|
|
|
|
|
|
push @{$newrows[-1]}, $_; |
1049
|
|
|
|
|
|
|
$tclients[$_] = [ $#newrows, $#{$newrows[-1]} ]; |
1050
|
|
|
|
|
|
|
$raised_row = $#newrows |
1051
|
|
|
|
|
|
|
if ($Raised && $client->[DTF_IDX_WIDGET] && |
1052
|
|
|
|
|
|
|
($client->[DTF_IDX_WIDGET] eq $Raised)); |
1053
|
|
|
|
|
|
|
} |
1054
|
|
|
|
|
|
|
} |
1055
|
|
|
|
|
|
|
# |
1056
|
|
|
|
|
|
|
# if number of rows exceeds our limit |
1057
|
|
|
|
|
|
|
# |
1058
|
|
|
|
|
|
|
return undef |
1059
|
|
|
|
|
|
|
if ($#newrows > DTF_MAX_ROWS); |
1060
|
|
|
|
|
|
|
# |
1061
|
|
|
|
|
|
|
# save the new row lists |
1062
|
|
|
|
|
|
|
# |
1063
|
|
|
|
|
|
|
$this->{RowList} = \@newrows; |
1064
|
|
|
|
|
|
|
$rows = \@newrows; |
1065
|
|
|
|
|
|
|
foreach my $row (@$rows) { |
1066
|
|
|
|
|
|
|
$clients->[$_]->[DTF_IDX_ROW] = $tclients[$_][0], |
1067
|
|
|
|
|
|
|
$clients->[$_]->[DTF_IDX_COL] = $tclients[$_][1] |
1068
|
|
|
|
|
|
|
foreach (@$row); |
1069
|
|
|
|
|
|
|
} |
1070
|
|
|
|
|
|
|
} |
1071
|
|
|
|
|
|
|
# |
1072
|
|
|
|
|
|
|
# purge all our pseudotabs |
1073
|
|
|
|
|
|
|
# |
1074
|
|
|
|
|
|
|
foreach (@$pseudos) { |
1075
|
|
|
|
|
|
|
next unless $_; |
1076
|
|
|
|
|
|
|
$_->placeForget() |
1077
|
|
|
|
|
|
|
if $_->ismapped(); |
1078
|
|
|
|
|
|
|
} |
1079
|
|
|
|
|
|
|
# |
1080
|
|
|
|
|
|
|
# undraw all our buttons |
1081
|
|
|
|
|
|
|
# |
1082
|
|
|
|
|
|
|
foreach my $i (0..$#$rows) { |
1083
|
|
|
|
|
|
|
foreach (@{$rows->[$i]}) { |
1084
|
|
|
|
|
|
|
$clients->[$_][DTF_IDX_FRAME]->placeForget() |
1085
|
|
|
|
|
|
|
if $clients->[$_][DTF_IDX_FRAME]->ismapped(); |
1086
|
|
|
|
|
|
|
} |
1087
|
|
|
|
|
|
|
} |
1088
|
|
|
|
|
|
|
# |
1089
|
|
|
|
|
|
|
# adjust our frame height to accomodate the rows |
1090
|
|
|
|
|
|
|
# |
1091
|
|
|
|
|
|
|
my $dim = $horizontal ? '-height' : '-width'; |
1092
|
|
|
|
|
|
|
$ButtonFrame->configure( |
1093
|
|
|
|
|
|
|
$dim => $this->GetButtonRowHeight($#$rows) + |
1094
|
|
|
|
|
|
|
($downward ? 5 : 7)); |
1095
|
|
|
|
|
|
|
# |
1096
|
|
|
|
|
|
|
# reconfig tabs to match height of tallest tab in row |
1097
|
|
|
|
|
|
|
# |
1098
|
|
|
|
|
|
|
my @hts = (); |
1099
|
|
|
|
|
|
|
push @hts, $this->GetRowHeight($_) |
1100
|
|
|
|
|
|
|
foreach (0..$#$rows); |
1101
|
|
|
|
|
|
|
# |
1102
|
|
|
|
|
|
|
# redraw all our buttons, starting from the top row |
1103
|
|
|
|
|
|
|
# note: we force each button to fully fill the button frame; |
1104
|
|
|
|
|
|
|
# this improves the visual effect when an upper tab extends |
1105
|
|
|
|
|
|
|
# to the right of the end of the row below it |
1106
|
|
|
|
|
|
|
# |
1107
|
|
|
|
|
|
|
my $Connector = $this->Subwidget('Connector'); |
1108
|
|
|
|
|
|
|
$Connector->placeForget(); # if $Connector->is_mapped(); |
1109
|
|
|
|
|
|
|
my ($i, $x, $y, $client, $frame); |
1110
|
|
|
|
|
|
|
if ($horizontal) { |
1111
|
|
|
|
|
|
|
if ($downward) { |
1112
|
|
|
|
|
|
|
# |
1113
|
|
|
|
|
|
|
# top tabs: |
1114
|
|
|
|
|
|
|
# draw from outermost row to innermost |
1115
|
|
|
|
|
|
|
# |
1116
|
|
|
|
|
|
|
$i = $#$rows; |
1117
|
|
|
|
|
|
|
$y = 0; |
1118
|
|
|
|
|
|
|
$x = 0; |
1119
|
|
|
|
|
|
|
while ($i >= 0) { |
1120
|
|
|
|
|
|
|
$x = ($alignment eq 'e') ? 0 : $ButtonFrame->width() - 8; |
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
foreach (0..$#{$rows->[$i]}) { |
1123
|
|
|
|
|
|
|
$client = $clients->[$rows->[$i][$_]]; |
1124
|
|
|
|
|
|
|
$frame = $client->[DTF_IDX_FRAME]; |
1125
|
|
|
|
|
|
|
$x -= ($client->[DTF_IDX_WIDTH] + $extra) |
1126
|
|
|
|
|
|
|
if ($alignment eq 'w'); |
1127
|
|
|
|
|
|
|
$frame->Subwidget('Button')->configure( |
1128
|
|
|
|
|
|
|
-height => $hts[$i]); |
1129
|
|
|
|
|
|
|
$frame->place( |
1130
|
|
|
|
|
|
|
-x => $x, |
1131
|
|
|
|
|
|
|
-y => $y, |
1132
|
|
|
|
|
|
|
-height => $hts[$i] + 6 |
1133
|
|
|
|
|
|
|
); |
1134
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
$x += $client->[DTF_IDX_WIDTH] + $extra |
1136
|
|
|
|
|
|
|
if ($alignment eq 'e'); |
1137
|
|
|
|
|
|
|
} |
1138
|
|
|
|
|
|
|
# |
1139
|
|
|
|
|
|
|
# draw pseudotabs if needed |
1140
|
|
|
|
|
|
|
# |
1141
|
|
|
|
|
|
|
$y = $y + $this->GetRowHeight($i) |
1142
|
|
|
|
|
|
|
if $i; |
1143
|
|
|
|
|
|
|
$pseudoht = $this->GetButtonRowHeight($i-1) + 6, |
1144
|
|
|
|
|
|
|
$pseudos->[$i]->place( |
1145
|
|
|
|
|
|
|
-x => 0, |
1146
|
|
|
|
|
|
|
-y => $y + 4, |
1147
|
|
|
|
|
|
|
-width => $ButtonFrame->width() - 8, |
1148
|
|
|
|
|
|
|
-height => $pseudoht) |
1149
|
|
|
|
|
|
|
if $i; |
1150
|
|
|
|
|
|
|
$i--; |
1151
|
|
|
|
|
|
|
} |
1152
|
|
|
|
|
|
|
} |
1153
|
|
|
|
|
|
|
else { |
1154
|
|
|
|
|
|
|
# |
1155
|
|
|
|
|
|
|
# bottom tabs: |
1156
|
|
|
|
|
|
|
# draw from innermost row to innermost |
1157
|
|
|
|
|
|
|
# |
1158
|
|
|
|
|
|
|
$i = 0; |
1159
|
|
|
|
|
|
|
$y = 0; |
1160
|
|
|
|
|
|
|
while ($i <= $#$rows) { |
1161
|
|
|
|
|
|
|
$x = ($alignment eq 'e') ? 0 : $ButtonFrame->width() - 8; |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
foreach (0..$#{$rows->[$i]}) { |
1164
|
|
|
|
|
|
|
$client = $clients->[$rows->[$i][$_]]; |
1165
|
|
|
|
|
|
|
$frame = $client->[DTF_IDX_FRAME]; |
1166
|
|
|
|
|
|
|
$x -= ($client->[DTF_IDX_WIDTH] + $extra) |
1167
|
|
|
|
|
|
|
if ($alignment eq 'w'); |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
$frame->Subwidget('Button')->configure( |
1170
|
|
|
|
|
|
|
-height => $hts[$i]); |
1171
|
|
|
|
|
|
|
$frame->place( |
1172
|
|
|
|
|
|
|
-x => $x, |
1173
|
|
|
|
|
|
|
-y => $y, |
1174
|
|
|
|
|
|
|
-height => $hts[$i] + 6 |
1175
|
|
|
|
|
|
|
); |
1176
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
$x += $client->[DTF_IDX_WIDTH] + $extra |
1178
|
|
|
|
|
|
|
if ($alignment eq 'e'); |
1179
|
|
|
|
|
|
|
} |
1180
|
|
|
|
|
|
|
# |
1181
|
|
|
|
|
|
|
# draw pseudotabs if needed |
1182
|
|
|
|
|
|
|
# |
1183
|
|
|
|
|
|
|
$pseudoht = $this->GetButtonRowHeight($i-1) + 1, |
1184
|
|
|
|
|
|
|
$pseudos->[$i]->place( |
1185
|
|
|
|
|
|
|
-x => 0, |
1186
|
|
|
|
|
|
|
-y => 0, |
1187
|
|
|
|
|
|
|
-width => $ButtonFrame->width() - 8, |
1188
|
|
|
|
|
|
|
-height => $pseudoht) |
1189
|
|
|
|
|
|
|
if $i; |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
$y = $y + $this->GetRowHeight($i); |
1192
|
|
|
|
|
|
|
$i++; |
1193
|
|
|
|
|
|
|
} # end while |
1194
|
|
|
|
|
|
|
} # end if downward...else... |
1195
|
|
|
|
|
|
|
} # end if horizontal |
1196
|
|
|
|
|
|
|
else { # vertical tabs |
1197
|
|
|
|
|
|
|
if ($downward) { |
1198
|
|
|
|
|
|
|
# |
1199
|
|
|
|
|
|
|
# left tabs: |
1200
|
|
|
|
|
|
|
# draw from outermost row to innermost |
1201
|
|
|
|
|
|
|
# |
1202
|
|
|
|
|
|
|
$i = $#$rows; |
1203
|
|
|
|
|
|
|
$x = 0; |
1204
|
|
|
|
|
|
|
while ($i >= 0) { |
1205
|
|
|
|
|
|
|
$y = ($alignment eq 's') ? 0 : $ButtonFrame->height() - 8; |
1206
|
|
|
|
|
|
|
|
1207
|
|
|
|
|
|
|
foreach (0..$#{$rows->[$i]}) { |
1208
|
|
|
|
|
|
|
$client = $clients->[$rows->[$i][$_]]; |
1209
|
|
|
|
|
|
|
$frame = $client->[DTF_IDX_FRAME]; |
1210
|
|
|
|
|
|
|
$y -= ($client->[DTF_IDX_WIDTH] + $extra) |
1211
|
|
|
|
|
|
|
if ($alignment eq 'n'); |
1212
|
|
|
|
|
|
|
|
1213
|
|
|
|
|
|
|
$frame->Subwidget('Button')->configure(-width => $hts[$i]); |
1214
|
|
|
|
|
|
|
$frame->place( |
1215
|
|
|
|
|
|
|
-x => $x, |
1216
|
|
|
|
|
|
|
-y => $y, |
1217
|
|
|
|
|
|
|
-width => $hts[$i] + 6 |
1218
|
|
|
|
|
|
|
); |
1219
|
|
|
|
|
|
|
|
1220
|
|
|
|
|
|
|
$y += $client->[DTF_IDX_WIDTH] + $extra |
1221
|
|
|
|
|
|
|
if ($alignment eq 's'); |
1222
|
|
|
|
|
|
|
} |
1223
|
|
|
|
|
|
|
# |
1224
|
|
|
|
|
|
|
# draw pseudotabs if needed |
1225
|
|
|
|
|
|
|
# |
1226
|
|
|
|
|
|
|
$x += $this->GetRowHeight($i); |
1227
|
|
|
|
|
|
|
$pseudoht = $this->GetButtonRowWidth($i-1) + 6, |
1228
|
|
|
|
|
|
|
$pseudos->[$i]->place( |
1229
|
|
|
|
|
|
|
-x => $x + 4, |
1230
|
|
|
|
|
|
|
-y => 0, |
1231
|
|
|
|
|
|
|
-width => $pseudoht, |
1232
|
|
|
|
|
|
|
-height => $ButtonFrame->height() - 8) |
1233
|
|
|
|
|
|
|
if $i; |
1234
|
|
|
|
|
|
|
$i--; |
1235
|
|
|
|
|
|
|
} |
1236
|
|
|
|
|
|
|
} |
1237
|
|
|
|
|
|
|
else { |
1238
|
|
|
|
|
|
|
# |
1239
|
|
|
|
|
|
|
# right tabs: |
1240
|
|
|
|
|
|
|
# draw from innermost row to innermost |
1241
|
|
|
|
|
|
|
# |
1242
|
|
|
|
|
|
|
$i = 0; |
1243
|
|
|
|
|
|
|
$x = 0; |
1244
|
|
|
|
|
|
|
while ($i <= $#$rows) { |
1245
|
|
|
|
|
|
|
$y = ($alignment eq 's') ? 0 : $ButtonFrame->height() - 8; |
1246
|
|
|
|
|
|
|
|
1247
|
|
|
|
|
|
|
foreach (0..$#{$rows->[$i]}) { |
1248
|
|
|
|
|
|
|
$client = $clients->[$rows->[$i][$_]]; |
1249
|
|
|
|
|
|
|
$frame = $client->[DTF_IDX_FRAME]; |
1250
|
|
|
|
|
|
|
$y -= ($client->[DTF_IDX_WIDTH] + $extra) |
1251
|
|
|
|
|
|
|
if ($alignment eq 'n'); |
1252
|
|
|
|
|
|
|
|
1253
|
|
|
|
|
|
|
$frame->Subwidget('Button')->configure(-width => $hts[$i]); |
1254
|
|
|
|
|
|
|
$frame->place( |
1255
|
|
|
|
|
|
|
-x => $x, |
1256
|
|
|
|
|
|
|
-y => $y, |
1257
|
|
|
|
|
|
|
-width => $hts[$i] + 6 |
1258
|
|
|
|
|
|
|
); |
1259
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
$y += $client->[DTF_IDX_WIDTH] + $extra |
1261
|
|
|
|
|
|
|
if ($alignment eq 's'); |
1262
|
|
|
|
|
|
|
} |
1263
|
|
|
|
|
|
|
# |
1264
|
|
|
|
|
|
|
# draw pseudotabs if needed |
1265
|
|
|
|
|
|
|
# |
1266
|
|
|
|
|
|
|
$pseudoht = $this->GetButtonRowHeight($i-1), |
1267
|
|
|
|
|
|
|
$pseudos->[$i]->place( |
1268
|
|
|
|
|
|
|
-x => $x - $pseudoht, |
1269
|
|
|
|
|
|
|
-y => 0, |
1270
|
|
|
|
|
|
|
-width => $pseudoht + 1, |
1271
|
|
|
|
|
|
|
-height => $ButtonFrame->height() - 8) |
1272
|
|
|
|
|
|
|
if $i; |
1273
|
|
|
|
|
|
|
$x += $this->GetRowHeight($i); |
1274
|
|
|
|
|
|
|
$i++; |
1275
|
|
|
|
|
|
|
} # end while |
1276
|
|
|
|
|
|
|
} # end if downward...else... |
1277
|
|
|
|
|
|
|
} # end if horizontal...else... |
1278
|
|
|
|
|
|
|
# |
1279
|
|
|
|
|
|
|
# and reapply our tab order |
1280
|
|
|
|
|
|
|
# |
1281
|
|
|
|
|
|
|
$this->TabOrder; |
1282
|
|
|
|
|
|
|
# |
1283
|
|
|
|
|
|
|
# and reraise in case raised ended up somewhere other than |
1284
|
|
|
|
|
|
|
# bottom row |
1285
|
|
|
|
|
|
|
# |
1286
|
|
|
|
|
|
|
$this->TabRaise($Raised, 1) if $Raised; |
1287
|
|
|
|
|
|
|
|
1288
|
|
|
|
|
|
|
return 1; |
1289
|
|
|
|
|
|
|
} |
1290
|
|
|
|
|
|
|
# |
1291
|
|
|
|
|
|
|
# remove a single tab and re-org the tabs |
1292
|
|
|
|
|
|
|
# |
1293
|
|
|
|
|
|
|
sub TabRemove { |
1294
|
|
|
|
|
|
|
my ($this, $Caption) = @_; |
1295
|
|
|
|
|
|
|
$this->{Updating} = 1; |
1296
|
|
|
|
|
|
|
# |
1297
|
|
|
|
|
|
|
# remove a tab |
1298
|
|
|
|
|
|
|
# |
1299
|
|
|
|
|
|
|
return undef |
1300
|
|
|
|
|
|
|
unless defined($this->{ClientHash}{$Caption}); |
1301
|
|
|
|
|
|
|
|
1302
|
|
|
|
|
|
|
my $rows = $this->{RowList}; |
1303
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
1304
|
|
|
|
|
|
|
my $listsz = $#$clients; |
1305
|
|
|
|
|
|
|
my $clientno = $this->{ClientHash}{$Caption}; |
1306
|
|
|
|
|
|
|
my $client = $clients->[$clientno]; |
1307
|
|
|
|
|
|
|
my $Widget = $client->[DTF_IDX_WIDGET]; |
1308
|
|
|
|
|
|
|
my ($r, $c) = ($client->[DTF_IDX_ROW], $client->[DTF_IDX_COL]); |
1309
|
|
|
|
|
|
|
# |
1310
|
|
|
|
|
|
|
# if its the raised widget, then we need to raise |
1311
|
|
|
|
|
|
|
# a tab to replace it (unless its the only widget) |
1312
|
|
|
|
|
|
|
# ...whatever is left at 0,0 sounds good to me... |
1313
|
|
|
|
|
|
|
# |
1314
|
|
|
|
|
|
|
my $row = $rows->[$r]; |
1315
|
|
|
|
|
|
|
my $newcurrent = ($client->[DTF_IDX_WIDGET] eq $this->{Raised}) ? 1 : undef; |
1316
|
|
|
|
|
|
|
# |
1317
|
|
|
|
|
|
|
# remove client from lists |
1318
|
|
|
|
|
|
|
# |
1319
|
|
|
|
|
|
|
delete $this->{ClientHash}{$Caption}; |
1320
|
|
|
|
|
|
|
|
1321
|
|
|
|
|
|
|
if ($clientno eq $#$clients) { |
1322
|
|
|
|
|
|
|
# Perl bug ? we seem to not get spliced out at ends |
1323
|
|
|
|
|
|
|
pop @$clients; |
1324
|
|
|
|
|
|
|
} |
1325
|
|
|
|
|
|
|
else { |
1326
|
|
|
|
|
|
|
splice @$clients, $clientno, 1; |
1327
|
|
|
|
|
|
|
} |
1328
|
|
|
|
|
|
|
splice @$row, $c, 1; |
1329
|
|
|
|
|
|
|
# |
1330
|
|
|
|
|
|
|
# adjust client positions in this row |
1331
|
|
|
|
|
|
|
# |
1332
|
|
|
|
|
|
|
$clients->[$row->[$_]][DTF_IDX_COL]-- |
1333
|
|
|
|
|
|
|
foreach ($c..$#$row); |
1334
|
|
|
|
|
|
|
# |
1335
|
|
|
|
|
|
|
# adjust client indices in the hash |
1336
|
|
|
|
|
|
|
# |
1337
|
|
|
|
|
|
|
foreach (keys %{$this->{ClientHash}}) { |
1338
|
|
|
|
|
|
|
$this->{ClientHash}{$_} -= 1 |
1339
|
|
|
|
|
|
|
if ($this->{ClientHash}{$_} > $clientno); |
1340
|
|
|
|
|
|
|
} |
1341
|
|
|
|
|
|
|
# |
1342
|
|
|
|
|
|
|
# adjust all our row index lists |
1343
|
|
|
|
|
|
|
# |
1344
|
|
|
|
|
|
|
foreach my $row (@$rows) { |
1345
|
|
|
|
|
|
|
foreach (0..$#$row) { |
1346
|
|
|
|
|
|
|
$row->[$_]-- if ($row->[$_] > $clientno); |
1347
|
|
|
|
|
|
|
} |
1348
|
|
|
|
|
|
|
} |
1349
|
|
|
|
|
|
|
|
1350
|
|
|
|
|
|
|
my $TabFrame = $client->[DTF_IDX_FRAME]; |
1351
|
|
|
|
|
|
|
$TabFrame->packForget(); |
1352
|
|
|
|
|
|
|
$TabFrame->destroy(); |
1353
|
|
|
|
|
|
|
$Widget->destroy(); |
1354
|
|
|
|
|
|
|
# |
1355
|
|
|
|
|
|
|
# if only tab in row, remove the row |
1356
|
|
|
|
|
|
|
# and adjust the clients in following rows |
1357
|
|
|
|
|
|
|
# |
1358
|
|
|
|
|
|
|
if ($#$row < 0) { |
1359
|
|
|
|
|
|
|
foreach my $i ($r+1..$#$rows) { |
1360
|
|
|
|
|
|
|
$row = $rows->[$i]; |
1361
|
|
|
|
|
|
|
$clients->[$_][DTF_IDX_ROW] -= 1 |
1362
|
|
|
|
|
|
|
foreach (@$row); |
1363
|
|
|
|
|
|
|
} |
1364
|
|
|
|
|
|
|
splice @$rows, $r, 1; |
1365
|
|
|
|
|
|
|
} |
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
if ($#$rows < 0) { |
1368
|
|
|
|
|
|
|
# |
1369
|
|
|
|
|
|
|
# no rows left, clear everything |
1370
|
|
|
|
|
|
|
# |
1371
|
|
|
|
|
|
|
$this->{Raised} = undef; |
1372
|
|
|
|
|
|
|
$this->Subwidget('Connector')->placeForget(); |
1373
|
|
|
|
|
|
|
$this->{CurrentFrame} = undef; |
1374
|
|
|
|
|
|
|
} |
1375
|
|
|
|
|
|
|
elsif ($newcurrent) { |
1376
|
|
|
|
|
|
|
$this->{Raised} = $clients->[$rows->[0][0]][DTF_IDX_WIDGET]; |
1377
|
|
|
|
|
|
|
} |
1378
|
|
|
|
|
|
|
# |
1379
|
|
|
|
|
|
|
# redraw everything |
1380
|
|
|
|
|
|
|
# |
1381
|
|
|
|
|
|
|
$this->TabRedraw(1); |
1382
|
|
|
|
|
|
|
$this->{Updating} = undef; |
1383
|
|
|
|
|
|
|
# |
1384
|
|
|
|
|
|
|
# odd behavior (maybe Resize timing issue): |
1385
|
|
|
|
|
|
|
# we occasionally end up with an undef entry at the tail |
1386
|
|
|
|
|
|
|
# |
1387
|
|
|
|
|
|
|
pop @$clients |
1388
|
|
|
|
|
|
|
unless (($listsz - 1) == $#$clients); |
1389
|
|
|
|
|
|
|
return 1; |
1390
|
|
|
|
|
|
|
} |
1391
|
|
|
|
|
|
|
# |
1392
|
|
|
|
|
|
|
# reveal a previously hidden tab and re-org the tabs |
1393
|
|
|
|
|
|
|
# |
1394
|
|
|
|
|
|
|
sub TabReveal { |
1395
|
|
|
|
|
|
|
my ($this, $Caption) = @_; |
1396
|
|
|
|
|
|
|
$this->{Updating} = 1; |
1397
|
|
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
return undef |
1399
|
|
|
|
|
|
|
unless defined($this->{ClientHash}{$Caption}); |
1400
|
|
|
|
|
|
|
|
1401
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
1402
|
|
|
|
|
|
|
my $rows = $this->{RowList}; |
1403
|
|
|
|
|
|
|
my $clientno = $this->{ClientHash}{$Caption}; |
1404
|
|
|
|
|
|
|
my $client = $clients->[$clientno]; |
1405
|
|
|
|
|
|
|
return 1 |
1406
|
|
|
|
|
|
|
unless $client->[DTF_IDX_HIDDEN]; |
1407
|
|
|
|
|
|
|
# |
1408
|
|
|
|
|
|
|
# make visible and redraw; note we don't |
1409
|
|
|
|
|
|
|
# make it raised yet |
1410
|
|
|
|
|
|
|
# |
1411
|
|
|
|
|
|
|
$client->[DTF_IDX_HIDDEN] = undef; |
1412
|
|
|
|
|
|
|
# |
1413
|
|
|
|
|
|
|
# pack tab in our rowframe 0; redraw if needed |
1414
|
|
|
|
|
|
|
# move everything over 1 column in bottom row |
1415
|
|
|
|
|
|
|
# |
1416
|
|
|
|
|
|
|
$clients->[$_][DTF_IDX_COL]++ |
1417
|
|
|
|
|
|
|
foreach (@{$rows->[0]}); |
1418
|
|
|
|
|
|
|
unshift @{$rows->[0]}, $clientno; |
1419
|
|
|
|
|
|
|
# |
1420
|
|
|
|
|
|
|
# redraw everything |
1421
|
|
|
|
|
|
|
# |
1422
|
|
|
|
|
|
|
$this->TabRedraw(1); |
1423
|
|
|
|
|
|
|
$this->{Updating} = undef; |
1424
|
|
|
|
|
|
|
# |
1425
|
|
|
|
|
|
|
# if nothing is raised, then raise us |
1426
|
|
|
|
|
|
|
# |
1427
|
|
|
|
|
|
|
$this->raise($Caption) |
1428
|
|
|
|
|
|
|
unless $this->{Raised}; |
1429
|
|
|
|
|
|
|
return 1; |
1430
|
|
|
|
|
|
|
} |
1431
|
|
|
|
|
|
|
# |
1432
|
|
|
|
|
|
|
# hide a single tab and re-org the tabs |
1433
|
|
|
|
|
|
|
# |
1434
|
|
|
|
|
|
|
sub TabHide { |
1435
|
|
|
|
|
|
|
my ($this, $Caption) = @_; |
1436
|
|
|
|
|
|
|
$this->{Updating} = 1; |
1437
|
|
|
|
|
|
|
|
1438
|
|
|
|
|
|
|
return undef |
1439
|
|
|
|
|
|
|
unless defined($this->{ClientHash}{$Caption}); |
1440
|
|
|
|
|
|
|
|
1441
|
|
|
|
|
|
|
my $rows = $this->{RowList}; |
1442
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
1443
|
|
|
|
|
|
|
my $listsz = $#$clients; |
1444
|
|
|
|
|
|
|
my $clientno = $this->{ClientHash}{$Caption}; |
1445
|
|
|
|
|
|
|
my $client = $clients->[$clientno]; |
1446
|
|
|
|
|
|
|
my $Widget = $client->[DTF_IDX_WIDGET]; |
1447
|
|
|
|
|
|
|
my ($r, $c) = ($client->[DTF_IDX_ROW], $client->[DTF_IDX_COL]); |
1448
|
|
|
|
|
|
|
# |
1449
|
|
|
|
|
|
|
# if its the raised widget, then we need to raise |
1450
|
|
|
|
|
|
|
# a tab to replace it (unless its the only widget) |
1451
|
|
|
|
|
|
|
# ...whatever is left at 0,0 sounds good to me... |
1452
|
|
|
|
|
|
|
# |
1453
|
|
|
|
|
|
|
my $row = $rows->[$r]; |
1454
|
|
|
|
|
|
|
my $newcurrent = ($client->[DTF_IDX_WIDGET] eq $this->{Raised}) ? 1 : undef; |
1455
|
|
|
|
|
|
|
# |
1456
|
|
|
|
|
|
|
# hide the client |
1457
|
|
|
|
|
|
|
# |
1458
|
|
|
|
|
|
|
$client->[DTF_IDX_HIDDEN] = 1; |
1459
|
|
|
|
|
|
|
$client->[DTF_IDX_ROW] = undef; |
1460
|
|
|
|
|
|
|
$client->[DTF_IDX_COL] = undef; |
1461
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
splice @$row, $c, 1; |
1463
|
|
|
|
|
|
|
# |
1464
|
|
|
|
|
|
|
# adjust client positions in this row |
1465
|
|
|
|
|
|
|
# |
1466
|
|
|
|
|
|
|
$clients->[$row->[$_]][DTF_IDX_COL]-- |
1467
|
|
|
|
|
|
|
foreach ($c..$#$row); |
1468
|
|
|
|
|
|
|
# |
1469
|
|
|
|
|
|
|
# adjust all our row index lists |
1470
|
|
|
|
|
|
|
# |
1471
|
|
|
|
|
|
|
# foreach my $row (@$rows) { |
1472
|
|
|
|
|
|
|
# foreach (0..$#$row) { |
1473
|
|
|
|
|
|
|
# $row->[$_]-- if ($row->[$_] > $clientno); |
1474
|
|
|
|
|
|
|
# } |
1475
|
|
|
|
|
|
|
# } |
1476
|
|
|
|
|
|
|
# |
1477
|
|
|
|
|
|
|
# force us into unraised color |
1478
|
|
|
|
|
|
|
# |
1479
|
|
|
|
|
|
|
my $TabFrame = $this->{ButtonFrame}->Subwidget('Button_'.$Widget); |
1480
|
|
|
|
|
|
|
$TabFrame->configure(-background => $client->[DTF_IDX_COLOR]); |
1481
|
|
|
|
|
|
|
$TabFrame->Subwidget('Button')->configure( |
1482
|
|
|
|
|
|
|
-bg => $client->[DTF_IDX_COLOR], |
1483
|
|
|
|
|
|
|
-activebackground => $client->[DTF_IDX_COLOR]); |
1484
|
|
|
|
|
|
|
|
1485
|
|
|
|
|
|
|
$client->[DTF_IDX_FRAME]->placeForget() |
1486
|
|
|
|
|
|
|
if $client->[DTF_IDX_FRAME]->ismapped(); |
1487
|
|
|
|
|
|
|
# |
1488
|
|
|
|
|
|
|
# if only tab in row, remove the row |
1489
|
|
|
|
|
|
|
# and adjust the clients in following rows |
1490
|
|
|
|
|
|
|
# |
1491
|
|
|
|
|
|
|
if ($#$row < 0) { |
1492
|
|
|
|
|
|
|
foreach my $i ($r+1..$#$rows) { |
1493
|
|
|
|
|
|
|
$row = $rows->[$i]; |
1494
|
|
|
|
|
|
|
$clients->[$_][DTF_IDX_ROW] -= 1 |
1495
|
|
|
|
|
|
|
foreach (@$row); |
1496
|
|
|
|
|
|
|
} |
1497
|
|
|
|
|
|
|
splice @$rows, $r, 1; |
1498
|
|
|
|
|
|
|
} |
1499
|
|
|
|
|
|
|
|
1500
|
|
|
|
|
|
|
if ($#$rows < 0) { |
1501
|
|
|
|
|
|
|
# |
1502
|
|
|
|
|
|
|
# no rows left, clear everything |
1503
|
|
|
|
|
|
|
# |
1504
|
|
|
|
|
|
|
$this->{Raised} = undef; |
1505
|
|
|
|
|
|
|
$this->Subwidget('Connector')->placeForget(); |
1506
|
|
|
|
|
|
|
$this->{CurrentFrame} = undef; |
1507
|
|
|
|
|
|
|
} |
1508
|
|
|
|
|
|
|
elsif ($newcurrent) { |
1509
|
|
|
|
|
|
|
$this->{Raised} = $clients->[$rows->[0][0]][DTF_IDX_WIDGET]; |
1510
|
|
|
|
|
|
|
} |
1511
|
|
|
|
|
|
|
# |
1512
|
|
|
|
|
|
|
# redraw everything |
1513
|
|
|
|
|
|
|
# |
1514
|
|
|
|
|
|
|
$this->TabRedraw(1); |
1515
|
|
|
|
|
|
|
$this->{Updating} = undef; |
1516
|
|
|
|
|
|
|
return 1; |
1517
|
|
|
|
|
|
|
} |
1518
|
|
|
|
|
|
|
# |
1519
|
|
|
|
|
|
|
# compute the tabbing traversal order |
1520
|
|
|
|
|
|
|
# note an anomaly: |
1521
|
|
|
|
|
|
|
# if the top row doesn't fill the frame, and a top |
1522
|
|
|
|
|
|
|
# row button is tabbed to, it is automatically moved |
1523
|
|
|
|
|
|
|
# to the 0,0, and its tab order it recomputed. This |
1524
|
|
|
|
|
|
|
# means that its impossible to tab to any tab |
1525
|
|
|
|
|
|
|
# in the top row except the first tab. We may eventually |
1526
|
|
|
|
|
|
|
# change TabRaise to bring the entire top row down |
1527
|
|
|
|
|
|
|
# if a top row tab is raised. |
1528
|
|
|
|
|
|
|
# |
1529
|
|
|
|
|
|
|
sub TabOrder { |
1530
|
|
|
|
|
|
|
my ($this) = @_; |
1531
|
|
|
|
|
|
|
|
1532
|
|
|
|
|
|
|
my $rows = $this->{RowList}; |
1533
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
1534
|
|
|
|
|
|
|
my ($prev, $next); |
1535
|
|
|
|
|
|
|
|
1536
|
|
|
|
|
|
|
foreach my $i (0..$#$rows) { |
1537
|
|
|
|
|
|
|
my $row = $rows->[$i]; |
1538
|
|
|
|
|
|
|
foreach my $j (0..$#$row) { |
1539
|
|
|
|
|
|
|
if ($j == 0) { |
1540
|
|
|
|
|
|
|
$prev = ($i == 0) ? $rows->[-1][-1] : $rows->[$i-1][-1]; |
1541
|
|
|
|
|
|
|
$next = ($#$row == 0) ? |
1542
|
|
|
|
|
|
|
($i == $#$rows) ? $rows->[0][0] : $rows->[$i+1][0] : |
1543
|
|
|
|
|
|
|
$row->[$j+1]; |
1544
|
|
|
|
|
|
|
} |
1545
|
|
|
|
|
|
|
elsif ($j == $#$row) { |
1546
|
|
|
|
|
|
|
$prev = $row->[$j-1]; |
1547
|
|
|
|
|
|
|
$next = ($i == $#$rows) ? $rows->[0][0] : $rows->[$i+1][0]; |
1548
|
|
|
|
|
|
|
} |
1549
|
|
|
|
|
|
|
else { |
1550
|
|
|
|
|
|
|
$prev = $row->[$j-1]; |
1551
|
|
|
|
|
|
|
$next = $row->[$j+1]; |
1552
|
|
|
|
|
|
|
} |
1553
|
|
|
|
|
|
|
|
1554
|
|
|
|
|
|
|
my $button = $clients->[$row->[$j]][DTF_IDX_FRAME]->Subwidget('Button'); |
1555
|
|
|
|
|
|
|
my $prevwgt = $clients->[$prev][DTF_IDX_WIDGET]; |
1556
|
|
|
|
|
|
|
my $prevbtn = $clients->[$prev][DTF_IDX_FRAME]->Subwidget('Button'); |
1557
|
|
|
|
|
|
|
my $nextwgt = $clients->[$next][DTF_IDX_WIDGET]; |
1558
|
|
|
|
|
|
|
my $nextbtn = $clients->[$next][DTF_IDX_FRAME]->Subwidget('Button'); |
1559
|
|
|
|
|
|
|
|
1560
|
|
|
|
|
|
|
# bind us |
1561
|
|
|
|
|
|
|
$button->bind ('', sub {$prevbtn->focus();}); |
1562
|
|
|
|
|
|
|
$button->bind ('', sub {$this->TabRaise($prevwgt);}); |
1563
|
|
|
|
|
|
|
$button->bind ('', sub {$nextbtn->focus();}); |
1564
|
|
|
|
|
|
|
$button->bind ('', sub {$this->TabRaise($nextwgt);}); |
1565
|
|
|
|
|
|
|
} |
1566
|
|
|
|
|
|
|
} |
1567
|
|
|
|
|
|
|
return 1; |
1568
|
|
|
|
|
|
|
} |
1569
|
|
|
|
|
|
|
# |
1570
|
|
|
|
|
|
|
# create a tooltip for the tab |
1571
|
|
|
|
|
|
|
# |
1572
|
|
|
|
|
|
|
sub CreateTabTip { |
1573
|
|
|
|
|
|
|
my ($this, $w, $btn, $tiptext) = @_; |
1574
|
|
|
|
|
|
|
# |
1575
|
|
|
|
|
|
|
# create balloon if none exists |
1576
|
|
|
|
|
|
|
# |
1577
|
|
|
|
|
|
|
$this->{Balloon} = $this->Component( |
1578
|
|
|
|
|
|
|
'Balloon' => 'Balloon', |
1579
|
|
|
|
|
|
|
-state => 'balloon', |
1580
|
|
|
|
|
|
|
-balloonposition => 'widget', |
1581
|
|
|
|
|
|
|
-initwait => $this->{_tiptime}, |
1582
|
|
|
|
|
|
|
-background => $this->{_tipcolor}) |
1583
|
|
|
|
|
|
|
unless $this->{Balloon}; |
1584
|
|
|
|
|
|
|
# |
1585
|
|
|
|
|
|
|
# attach a balloon if tiptext requested |
1586
|
|
|
|
|
|
|
# |
1587
|
|
|
|
|
|
|
$w->[DTF_IDX_TABTIP] = $tiptext; |
1588
|
|
|
|
|
|
|
return $this->{Balloon}->attach($btn, -balloonmsg => $tiptext); |
1589
|
|
|
|
|
|
|
} |
1590
|
|
|
|
|
|
|
# |
1591
|
|
|
|
|
|
|
# change tab's tip text |
1592
|
|
|
|
|
|
|
# |
1593
|
|
|
|
|
|
|
sub UpdateTabTip { |
1594
|
|
|
|
|
|
|
my ($this, $w, $btn, $tiptext) = @_; |
1595
|
|
|
|
|
|
|
|
1596
|
|
|
|
|
|
|
return undef unless $this->{Balloon}; |
1597
|
|
|
|
|
|
|
# |
1598
|
|
|
|
|
|
|
# attach a balloon if tiptext requested |
1599
|
|
|
|
|
|
|
# |
1600
|
|
|
|
|
|
|
$this->{Balloon}->detach($btn) |
1601
|
|
|
|
|
|
|
if $w->[DTF_IDX_TABTIP]; |
1602
|
|
|
|
|
|
|
$w->[DTF_IDX_TABTIP] = $tiptext; |
1603
|
|
|
|
|
|
|
return $this->{Balloon}->attach($btn, -balloonmsg => $tiptext); |
1604
|
|
|
|
|
|
|
} |
1605
|
|
|
|
|
|
|
|
1606
|
|
|
|
|
|
|
# |
1607
|
|
|
|
|
|
|
# remove a tooltip from the tab |
1608
|
|
|
|
|
|
|
# |
1609
|
|
|
|
|
|
|
sub RemoveTabTip { |
1610
|
|
|
|
|
|
|
my ($this, $w, $btn) = shift; |
1611
|
|
|
|
|
|
|
|
1612
|
|
|
|
|
|
|
return 1 unless $this->{Balloon}; |
1613
|
|
|
|
|
|
|
|
1614
|
|
|
|
|
|
|
$w->[DTF_IDX_TABTIP] = undef; |
1615
|
|
|
|
|
|
|
return $this->{Balloon}->detach($btn); |
1616
|
|
|
|
|
|
|
} |
1617
|
|
|
|
|
|
|
|
1618
|
|
|
|
|
|
|
sub current { |
1619
|
|
|
|
|
|
|
shift->TabCurrent (@_); |
1620
|
|
|
|
|
|
|
} |
1621
|
|
|
|
|
|
|
|
1622
|
|
|
|
|
|
|
sub add { |
1623
|
|
|
|
|
|
|
my $this = shift; |
1624
|
|
|
|
|
|
|
# |
1625
|
|
|
|
|
|
|
# make this Notebook compatible |
1626
|
|
|
|
|
|
|
# |
1627
|
|
|
|
|
|
|
my $caption; |
1628
|
|
|
|
|
|
|
$caption = shift |
1629
|
|
|
|
|
|
|
unless ($_[0]=~/^-(caption|tabcolor|raisecolor|tabtip|hidden|state|label|image|text)$/); |
1630
|
|
|
|
|
|
|
my %args = @_; |
1631
|
|
|
|
|
|
|
$caption = $args{-caption} unless $caption; |
1632
|
|
|
|
|
|
|
return undef unless defined($caption); |
1633
|
|
|
|
|
|
|
my $frame = $this->TabCreate( |
1634
|
|
|
|
|
|
|
$caption, |
1635
|
|
|
|
|
|
|
delete $args{'-tabcolor'}, |
1636
|
|
|
|
|
|
|
delete $args{'-raisecolor'}, |
1637
|
|
|
|
|
|
|
delete $args{'-image'}, |
1638
|
|
|
|
|
|
|
delete $args{'-label'}, |
1639
|
|
|
|
|
|
|
delete $args{'-raisecmd'}, |
1640
|
|
|
|
|
|
|
); |
1641
|
|
|
|
|
|
|
# |
1642
|
|
|
|
|
|
|
# pick up any attributes we didn't process during creation |
1643
|
|
|
|
|
|
|
# |
1644
|
|
|
|
|
|
|
$this->pageconfigure($caption, %args) |
1645
|
|
|
|
|
|
|
if ($frame && %args); |
1646
|
|
|
|
|
|
|
return $frame; |
1647
|
|
|
|
|
|
|
} |
1648
|
|
|
|
|
|
|
# |
1649
|
|
|
|
|
|
|
# turn off flashing tab |
1650
|
|
|
|
|
|
|
# |
1651
|
|
|
|
|
|
|
sub deflash { |
1652
|
|
|
|
|
|
|
my ($this, $page) = @_; |
1653
|
|
|
|
|
|
|
|
1654
|
|
|
|
|
|
|
return undef |
1655
|
|
|
|
|
|
|
unless defined($this->{ClientHash}{$page}); |
1656
|
|
|
|
|
|
|
|
1657
|
|
|
|
|
|
|
my $w = $this->{ClientList}[$this->{ClientHash}{$page}]; |
1658
|
|
|
|
|
|
|
my $color = (defined($this->{Raised}) && |
1659
|
|
|
|
|
|
|
($w->[DTF_IDX_WIDGET] eq $this->{Raised})) ? |
1660
|
|
|
|
|
|
|
$w->[DTF_IDX_RAISECOLOR] : |
1661
|
|
|
|
|
|
|
$w->[DTF_IDX_COLOR]; |
1662
|
|
|
|
|
|
|
my $frame = $w->[DTF_IDX_FRAME]; |
1663
|
|
|
|
|
|
|
$frame->configure(-bg => $color), |
1664
|
|
|
|
|
|
|
$frame->Subwidget('Button')->configure( |
1665
|
|
|
|
|
|
|
-bg => $color, -activebackground => $color), |
1666
|
|
|
|
|
|
|
$frame->afterCancel($w->[DTF_IDX_FLASH_ID]), |
1667
|
|
|
|
|
|
|
$w->[DTF_IDX_FLASH_ID] = $w->[DTF_IDX_FLASHED] = |
1668
|
|
|
|
|
|
|
$w->[DTF_IDX_FLASH_TIME] = undef |
1669
|
|
|
|
|
|
|
if $w->[DTF_IDX_FLASH_ID]; |
1670
|
|
|
|
|
|
|
return $this; |
1671
|
|
|
|
|
|
|
} |
1672
|
|
|
|
|
|
|
# |
1673
|
|
|
|
|
|
|
# flash a tab |
1674
|
|
|
|
|
|
|
# |
1675
|
|
|
|
|
|
|
sub flash { |
1676
|
|
|
|
|
|
|
my ($this, $page, %args) = @_; |
1677
|
|
|
|
|
|
|
|
1678
|
|
|
|
|
|
|
return undef |
1679
|
|
|
|
|
|
|
unless defined($this->{ClientHash}{$page}); |
1680
|
|
|
|
|
|
|
|
1681
|
|
|
|
|
|
|
my $w = $this->{ClientList}[$this->{ClientHash}{$page}]; |
1682
|
|
|
|
|
|
|
# |
1683
|
|
|
|
|
|
|
# don't start new flash if we already are |
1684
|
|
|
|
|
|
|
# |
1685
|
|
|
|
|
|
|
return $this if $w->[DTF_IDX_FLASH_ID]; |
1686
|
|
|
|
|
|
|
$args{-interval} = 300 unless $args{-interval}; |
1687
|
|
|
|
|
|
|
$args{-duration} = 5000 unless $args{-duration}; |
1688
|
|
|
|
|
|
|
|
1689
|
|
|
|
|
|
|
$w->[DTF_IDX_FLASH_COLOR] = $args{-color} ||= 'blue'; |
1690
|
|
|
|
|
|
|
$w->[DTF_IDX_FLASH_INTVL] = $args{-interval}; |
1691
|
|
|
|
|
|
|
$w->[DTF_IDX_FLASH_TIME] = Tk::timeofday() + ($args{-duration}/1000); |
1692
|
|
|
|
|
|
|
|
1693
|
|
|
|
|
|
|
$w->[DTF_IDX_FLASH_ID] = $w->[DTF_IDX_FRAME]->repeat( |
1694
|
|
|
|
|
|
|
$w->[DTF_IDX_FLASH_INTVL], |
1695
|
|
|
|
|
|
|
sub { |
1696
|
|
|
|
|
|
|
my $color = (defined($this->{Raised}) && |
1697
|
|
|
|
|
|
|
($w->[DTF_IDX_WIDGET] eq $this->{Raised})) ? |
1698
|
|
|
|
|
|
|
$w->[DTF_IDX_RAISECOLOR] : |
1699
|
|
|
|
|
|
|
$w->[DTF_IDX_COLOR]; |
1700
|
|
|
|
|
|
|
my $frame = $w->[DTF_IDX_FRAME]; |
1701
|
|
|
|
|
|
|
$frame->afterCancel($w->[DTF_IDX_FLASH_ID]), |
1702
|
|
|
|
|
|
|
$frame->configure(-bg => $color), |
1703
|
|
|
|
|
|
|
$frame->Subwidget('Button')->configure( |
1704
|
|
|
|
|
|
|
-bg => $color, -activebackground => $color), |
1705
|
|
|
|
|
|
|
$w->[DTF_IDX_FLASH_ID] = $w->[DTF_IDX_FLASHED] = |
1706
|
|
|
|
|
|
|
$w->[DTF_IDX_FLASH_TIME] = undef, |
1707
|
|
|
|
|
|
|
return 1 |
1708
|
|
|
|
|
|
|
if (Tk::timeofday() > $w->[DTF_IDX_FLASH_TIME]); |
1709
|
|
|
|
|
|
|
|
1710
|
|
|
|
|
|
|
$color = $w->[DTF_IDX_FLASH_COLOR] unless $w->[DTF_IDX_FLASHED]; |
1711
|
|
|
|
|
|
|
$frame->configure(-bg => $color); |
1712
|
|
|
|
|
|
|
$frame->Subwidget('Button')->configure( |
1713
|
|
|
|
|
|
|
-bg => $color, -activebackground => $color); |
1714
|
|
|
|
|
|
|
$w->[DTF_IDX_FLASHED] = ! $w->[DTF_IDX_FLASHED]; |
1715
|
|
|
|
|
|
|
return 1; |
1716
|
|
|
|
|
|
|
} |
1717
|
|
|
|
|
|
|
); |
1718
|
|
|
|
|
|
|
return $this; |
1719
|
|
|
|
|
|
|
} |
1720
|
|
|
|
|
|
|
|
1721
|
|
|
|
|
|
|
sub raised { |
1722
|
|
|
|
|
|
|
shift->TabCurrent (@_); |
1723
|
|
|
|
|
|
|
} |
1724
|
|
|
|
|
|
|
# |
1725
|
|
|
|
|
|
|
# return caption of current raised widget |
1726
|
|
|
|
|
|
|
# |
1727
|
|
|
|
|
|
|
sub raised_name { |
1728
|
|
|
|
|
|
|
my $this = shift; |
1729
|
|
|
|
|
|
|
|
1730
|
|
|
|
|
|
|
return undef unless $this->{Raised}; |
1731
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
1732
|
|
|
|
|
|
|
foreach my $client (@$clients) { |
1733
|
|
|
|
|
|
|
return $client->[DTF_IDX_CAPTION] |
1734
|
|
|
|
|
|
|
if ($client->[DTF_IDX_WIDGET] eq $this->{Raised}); |
1735
|
|
|
|
|
|
|
} |
1736
|
|
|
|
|
|
|
return undef; |
1737
|
|
|
|
|
|
|
} |
1738
|
|
|
|
|
|
|
# |
1739
|
|
|
|
|
|
|
# Notebook compatible methods |
1740
|
|
|
|
|
|
|
# |
1741
|
|
|
|
|
|
|
sub pagecget { |
1742
|
|
|
|
|
|
|
my ($this, $page, $option) = @_; |
1743
|
|
|
|
|
|
|
|
1744
|
|
|
|
|
|
|
return undef |
1745
|
|
|
|
|
|
|
unless (defined($this->{ClientHash}{$page}) && |
1746
|
|
|
|
|
|
|
defined($page_opts{$option})); |
1747
|
|
|
|
|
|
|
|
1748
|
|
|
|
|
|
|
return $page if ($option eq '-caption'); |
1749
|
|
|
|
|
|
|
|
1750
|
|
|
|
|
|
|
my $w = $this->{ClientList}[$this->{ClientHash}{$page}]; |
1751
|
|
|
|
|
|
|
return ($page_opts{$option}=~/^\d+/) ? |
1752
|
|
|
|
|
|
|
$w->[$page_opts{$option}] : |
1753
|
|
|
|
|
|
|
$w->[DTF_IDX_FRAME]->Subwidget('Button')->cget($page_opts{$option}); |
1754
|
|
|
|
|
|
|
} |
1755
|
|
|
|
|
|
|
|
1756
|
|
|
|
|
|
|
sub pageconfigure { |
1757
|
|
|
|
|
|
|
my ($this, $page, %args) = @_; |
1758
|
|
|
|
|
|
|
|
1759
|
|
|
|
|
|
|
return undef |
1760
|
|
|
|
|
|
|
unless defined($this->{ClientHash}{$page}); |
1761
|
|
|
|
|
|
|
# |
1762
|
|
|
|
|
|
|
# we're forgiving here if they supply an option we don't |
1763
|
|
|
|
|
|
|
# support |
1764
|
|
|
|
|
|
|
# |
1765
|
|
|
|
|
|
|
my $w = $this->{ClientList}[$this->{ClientHash}{$page}]; |
1766
|
|
|
|
|
|
|
my $btn = $w->[DTF_IDX_FRAME]->Subwidget('Button'); |
1767
|
|
|
|
|
|
|
foreach (keys %args) { |
1768
|
|
|
|
|
|
|
next unless defined($page_opts{$_}); |
1769
|
|
|
|
|
|
|
|
1770
|
|
|
|
|
|
|
if ($_ eq '-hidden') { |
1771
|
|
|
|
|
|
|
# |
1772
|
|
|
|
|
|
|
# check if hiding the page |
1773
|
|
|
|
|
|
|
# |
1774
|
|
|
|
|
|
|
if ($args{$_}) { |
1775
|
|
|
|
|
|
|
next if $w->[DTF_IDX_HIDDEN]; |
1776
|
|
|
|
|
|
|
$this->TabHide($page); |
1777
|
|
|
|
|
|
|
} |
1778
|
|
|
|
|
|
|
else { |
1779
|
|
|
|
|
|
|
# |
1780
|
|
|
|
|
|
|
# restore the tab if its hidden |
1781
|
|
|
|
|
|
|
# |
1782
|
|
|
|
|
|
|
$this->TabReveal($page) |
1783
|
|
|
|
|
|
|
if $w->[DTF_IDX_HIDDEN]; |
1784
|
|
|
|
|
|
|
} |
1785
|
|
|
|
|
|
|
next; |
1786
|
|
|
|
|
|
|
} |
1787
|
|
|
|
|
|
|
# |
1788
|
|
|
|
|
|
|
# make sure we apply state to the close button too |
1789
|
|
|
|
|
|
|
# |
1790
|
|
|
|
|
|
|
if ($_ eq '-state') { |
1791
|
|
|
|
|
|
|
if ($w->[DTF_IDX_FRAME]->Subwidget('CloseBtn')) { |
1792
|
|
|
|
|
|
|
$w->[DTF_IDX_FRAME]->Subwidget('CloseBtn')->configure(-state => $args{$_}); |
1793
|
|
|
|
|
|
|
} |
1794
|
|
|
|
|
|
|
$btn->configure(-state => $args{$_}); |
1795
|
|
|
|
|
|
|
} |
1796
|
|
|
|
|
|
|
next |
1797
|
|
|
|
|
|
|
if ($_ eq '-state'); |
1798
|
|
|
|
|
|
|
|
1799
|
|
|
|
|
|
|
$btn->configure($page_opts{$_} => $args{$_}), next |
1800
|
|
|
|
|
|
|
unless ($page_opts{$_}=~/^\d+/); |
1801
|
|
|
|
|
|
|
# |
1802
|
|
|
|
|
|
|
# create, update, or remove the button balloon |
1803
|
|
|
|
|
|
|
# |
1804
|
|
|
|
|
|
|
if ($_ eq '-tabtip') { |
1805
|
|
|
|
|
|
|
if ($w->[DTF_IDX_TABTIP]) { |
1806
|
|
|
|
|
|
|
if (defined($args{$_})) { |
1807
|
|
|
|
|
|
|
$this->UpdateTabTip($w, $btn, $args{$_}); |
1808
|
|
|
|
|
|
|
} |
1809
|
|
|
|
|
|
|
else { |
1810
|
|
|
|
|
|
|
$this->RemoveTabTip($w, $btn); |
1811
|
|
|
|
|
|
|
} |
1812
|
|
|
|
|
|
|
} |
1813
|
|
|
|
|
|
|
else { # no current tip, create one if requested |
1814
|
|
|
|
|
|
|
$this->CreateTabTip($w, $btn, $args{$_}) |
1815
|
|
|
|
|
|
|
if $args{$_}; |
1816
|
|
|
|
|
|
|
} |
1817
|
|
|
|
|
|
|
next; |
1818
|
|
|
|
|
|
|
} |
1819
|
|
|
|
|
|
|
|
1820
|
|
|
|
|
|
|
$w->[$page_opts{$_}] = $args{$_}; |
1821
|
|
|
|
|
|
|
# |
1822
|
|
|
|
|
|
|
# update the button text; be sure to rotate if needed |
1823
|
|
|
|
|
|
|
# |
1824
|
|
|
|
|
|
|
$btn->configure( |
1825
|
|
|
|
|
|
|
-text => ($taborient{$this->{Side}}[DTF_ORIENT_DIRECTION] ? |
1826
|
|
|
|
|
|
|
$w->[DTF_IDX_LABEL] : RotateTabText($w->[DTF_IDX_LABEL])) ), |
1827
|
|
|
|
|
|
|
next |
1828
|
|
|
|
|
|
|
if ($_ eq '-label'); |
1829
|
|
|
|
|
|
|
# |
1830
|
|
|
|
|
|
|
# reconfig the button and tab colors as needed |
1831
|
|
|
|
|
|
|
# |
1832
|
|
|
|
|
|
|
$btn->configure(-bg => $args{$_}), |
1833
|
|
|
|
|
|
|
$w->[DTF_IDX_FRAME]->configure(-bg => $args{$_}) |
1834
|
|
|
|
|
|
|
if ((($_ eq '-tabcolor') && |
1835
|
|
|
|
|
|
|
((! defined($this->{Raised})) || |
1836
|
|
|
|
|
|
|
($w->[DTF_IDX_WIDGET] ne $this->{Raised}))) || |
1837
|
|
|
|
|
|
|
(($_ eq '-raisecolor') && |
1838
|
|
|
|
|
|
|
(defined($this->{Raised}) && |
1839
|
|
|
|
|
|
|
($w->[DTF_IDX_WIDGET] eq $this->{Raised})))); |
1840
|
|
|
|
|
|
|
} |
1841
|
|
|
|
|
|
|
1; |
1842
|
|
|
|
|
|
|
} |
1843
|
|
|
|
|
|
|
|
1844
|
|
|
|
|
|
|
sub pages { |
1845
|
|
|
|
|
|
|
return keys %{shift->{ClientHash}}; |
1846
|
|
|
|
|
|
|
} |
1847
|
|
|
|
|
|
|
|
1848
|
|
|
|
|
|
|
sub tiptime { |
1849
|
|
|
|
|
|
|
my ($this, $time) = @_; |
1850
|
|
|
|
|
|
|
|
1851
|
|
|
|
|
|
|
return $this->{_tiptime} |
1852
|
|
|
|
|
|
|
unless defined($time); |
1853
|
|
|
|
|
|
|
$this->{_tiptime} = $time; |
1854
|
|
|
|
|
|
|
return $this->{Balloon} ? |
1855
|
|
|
|
|
|
|
$this->{Balloon}->configure(-initwait => $time) : 1; |
1856
|
|
|
|
|
|
|
} |
1857
|
|
|
|
|
|
|
|
1858
|
|
|
|
|
|
|
sub tipcolor { |
1859
|
|
|
|
|
|
|
my ($this, $color) = @_; |
1860
|
|
|
|
|
|
|
|
1861
|
|
|
|
|
|
|
return $this->{_tipcolor} |
1862
|
|
|
|
|
|
|
unless defined($color); |
1863
|
|
|
|
|
|
|
$this->{_tipcolor} = $color; |
1864
|
|
|
|
|
|
|
return $this->{Balloon} ? |
1865
|
|
|
|
|
|
|
$this->{Balloon}->configure(-background => $color) : 1; |
1866
|
|
|
|
|
|
|
} |
1867
|
|
|
|
|
|
|
|
1868
|
|
|
|
|
|
|
sub font { |
1869
|
|
|
|
|
|
|
shift->Font(@_); |
1870
|
|
|
|
|
|
|
} |
1871
|
|
|
|
|
|
|
# |
1872
|
|
|
|
|
|
|
# programatically raise a tab using its caption |
1873
|
|
|
|
|
|
|
# |
1874
|
|
|
|
|
|
|
sub raise { |
1875
|
|
|
|
|
|
|
my ($this, $Caption) = @_; |
1876
|
|
|
|
|
|
|
return defined($this->{ClientHash}{$Caption}) ? |
1877
|
|
|
|
|
|
|
$this->TabRaise($this->{ClientList}[$this->{ClientHash}{$Caption}][DTF_IDX_WIDGET]) : |
1878
|
|
|
|
|
|
|
undef; |
1879
|
|
|
|
|
|
|
} |
1880
|
|
|
|
|
|
|
# |
1881
|
|
|
|
|
|
|
# programatically remove a tab using its caption |
1882
|
|
|
|
|
|
|
# |
1883
|
|
|
|
|
|
|
sub delete { |
1884
|
|
|
|
|
|
|
my ($this, $Caption) = @_; |
1885
|
|
|
|
|
|
|
return defined($this->{ClientHash}{$Caption}) ? |
1886
|
|
|
|
|
|
|
$this->TabRemove($Caption) : undef; |
1887
|
|
|
|
|
|
|
} |
1888
|
|
|
|
|
|
|
# |
1889
|
|
|
|
|
|
|
# return a hash of our tabs keyed by caption, so the |
1890
|
|
|
|
|
|
|
# app can e.g., attach a Balloon to them |
1891
|
|
|
|
|
|
|
# |
1892
|
|
|
|
|
|
|
sub tabs { |
1893
|
|
|
|
|
|
|
my ($this) = @_; |
1894
|
|
|
|
|
|
|
my $tabs = { }; |
1895
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
1896
|
|
|
|
|
|
|
|
1897
|
|
|
|
|
|
|
$tabs->{$_} = $clients->[$this->{ClientHash}{$_}][DTF_IDX_FRAME] |
1898
|
|
|
|
|
|
|
foreach (keys %{$this->{ClientHash}}); |
1899
|
|
|
|
|
|
|
return $tabs; |
1900
|
|
|
|
|
|
|
} |
1901
|
|
|
|
|
|
|
|
1902
|
|
|
|
|
|
|
sub tabside { |
1903
|
|
|
|
|
|
|
my ($this, $side) = @_; |
1904
|
|
|
|
|
|
|
|
1905
|
|
|
|
|
|
|
return $this->{Side} unless defined($side); |
1906
|
|
|
|
|
|
|
# |
1907
|
|
|
|
|
|
|
# if already populated, don't permit change |
1908
|
|
|
|
|
|
|
# |
1909
|
|
|
|
|
|
|
return undef |
1910
|
|
|
|
|
|
|
unless ($side=~/^([ns][ew]?)|([ew][ns]?)$/i); |
1911
|
|
|
|
|
|
|
# |
1912
|
|
|
|
|
|
|
# if already populated, don't permit change |
1913
|
|
|
|
|
|
|
# |
1914
|
|
|
|
|
|
|
return undef |
1915
|
|
|
|
|
|
|
if $this->{PseudoTabs}; |
1916
|
|
|
|
|
|
|
|
1917
|
|
|
|
|
|
|
$side = lc $side; |
1918
|
|
|
|
|
|
|
$side .= 'w' if (($side eq 'n') || ($side eq 's')); |
1919
|
|
|
|
|
|
|
$side .= 'n' if (($side eq 'e') || ($side eq 'w')); |
1920
|
|
|
|
|
|
|
return $side if ($this->{Side} eq $side); |
1921
|
|
|
|
|
|
|
|
1922
|
|
|
|
|
|
|
my $oldside = $this->{Side}; |
1923
|
|
|
|
|
|
|
$this->{Side} = $side; |
1924
|
|
|
|
|
|
|
# |
1925
|
|
|
|
|
|
|
# modify all the tabs to move their buttons and closers |
1926
|
|
|
|
|
|
|
# |
1927
|
|
|
|
|
|
|
my $to = $taborient{$side}; |
1928
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
1929
|
|
|
|
|
|
|
my $tab; |
1930
|
|
|
|
|
|
|
my $padx = $this->cget(-tabpadx); |
1931
|
|
|
|
|
|
|
my $pady = $this->cget(-tabpady); |
1932
|
|
|
|
|
|
|
foreach (keys %{$this->{ClientHash}}) { |
1933
|
|
|
|
|
|
|
$tab = $clients->[$this->{ClientHash}{$_}]; |
1934
|
|
|
|
|
|
|
my $btn = $tab->[DTF_IDX_FRAME]->Subwidget('Button'); |
1935
|
|
|
|
|
|
|
$btn->packForget; |
1936
|
|
|
|
|
|
|
if ($tab->[DTF_IDX_FRAME]->Subwidget('CloseBtn')) { |
1937
|
|
|
|
|
|
|
# |
1938
|
|
|
|
|
|
|
# repack close tab |
1939
|
|
|
|
|
|
|
# |
1940
|
|
|
|
|
|
|
my $closer = $tab->[DTF_IDX_FRAME]->Subwidget('CloseBtn'); |
1941
|
|
|
|
|
|
|
$closer->packForget; |
1942
|
|
|
|
|
|
|
$closer->configure( |
1943
|
|
|
|
|
|
|
-anchor => $to->[DTF_ORIENT_CLOSEANCHOR]); |
1944
|
|
|
|
|
|
|
$closer->pack( |
1945
|
|
|
|
|
|
|
-side => $to->[DTF_ORIENT_CLOSESIDE], |
1946
|
|
|
|
|
|
|
-anchor => $to->[DTF_ORIENT_CLOSEANCHOR], |
1947
|
|
|
|
|
|
|
-expand => 0, |
1948
|
|
|
|
|
|
|
-fill => 'none', |
1949
|
|
|
|
|
|
|
-ipadx => 0, |
1950
|
|
|
|
|
|
|
-ipady => 0, |
1951
|
|
|
|
|
|
|
-padx => 1, |
1952
|
|
|
|
|
|
|
-pady => 1, |
1953
|
|
|
|
|
|
|
); |
1954
|
|
|
|
|
|
|
} |
1955
|
|
|
|
|
|
|
# |
1956
|
|
|
|
|
|
|
# rotate button text if needed |
1957
|
|
|
|
|
|
|
# |
1958
|
|
|
|
|
|
|
$btn->configure(-text => |
1959
|
|
|
|
|
|
|
($to->[DTF_ORIENT_DIRECTION] ? $tab->[DTF_IDX_LABEL] : |
1960
|
|
|
|
|
|
|
RotateTabText($tab->[DTF_IDX_LABEL]))) |
1961
|
|
|
|
|
|
|
if defined($btn->cget(-text)); |
1962
|
|
|
|
|
|
|
# |
1963
|
|
|
|
|
|
|
# repack the button |
1964
|
|
|
|
|
|
|
# |
1965
|
|
|
|
|
|
|
$btn->pack( |
1966
|
|
|
|
|
|
|
-side => $to->[DTF_ORIENT_BTNSIDE], |
1967
|
|
|
|
|
|
|
-anchor => $to->[DTF_ORIENT_BTNANCHOR], |
1968
|
|
|
|
|
|
|
-expand => 0, |
1969
|
|
|
|
|
|
|
-fill => 'none', |
1970
|
|
|
|
|
|
|
-ipadx => 0, |
1971
|
|
|
|
|
|
|
-ipady => 0, |
1972
|
|
|
|
|
|
|
-padx => $padx, |
1973
|
|
|
|
|
|
|
-pady => $pady, |
1974
|
|
|
|
|
|
|
); |
1975
|
|
|
|
|
|
|
# |
1976
|
|
|
|
|
|
|
# record new button size |
1977
|
|
|
|
|
|
|
# |
1978
|
|
|
|
|
|
|
$tab->[DTF_IDX_HEIGHT] = $to->[DTF_ORIENT_DIRECTION] ? |
1979
|
|
|
|
|
|
|
$btn->reqheight + (2 * $pady) : |
1980
|
|
|
|
|
|
|
$btn->reqwidth + (2 * $padx); |
1981
|
|
|
|
|
|
|
$tab->[DTF_IDX_WIDTH] = $to->[DTF_ORIENT_DIRECTION] ? |
1982
|
|
|
|
|
|
|
$btn->reqwidth + (2 * $padx) : |
1983
|
|
|
|
|
|
|
$btn->reqheight + (2 * $pady); |
1984
|
|
|
|
|
|
|
} |
1985
|
|
|
|
|
|
|
###################################################################### |
1986
|
|
|
|
|
|
|
# |
1987
|
|
|
|
|
|
|
# we must repack the major frame components for this to work; |
1988
|
|
|
|
|
|
|
# but this process may have some undesirable consequences, and probably |
1989
|
|
|
|
|
|
|
# requires that we do everything in a specific order... |
1990
|
|
|
|
|
|
|
# |
1991
|
|
|
|
|
|
|
###################################################################### |
1992
|
|
|
|
|
|
|
# |
1993
|
|
|
|
|
|
|
# get tab alignment info |
1994
|
|
|
|
|
|
|
# |
1995
|
|
|
|
|
|
|
my ($tabside, $tabfill, $tabanchor, $tabsize, $clientside) = |
1996
|
|
|
|
|
|
|
@{$tabalign{$side}}; |
1997
|
|
|
|
|
|
|
# |
1998
|
|
|
|
|
|
|
# unplace the pseudo tabs, |
1999
|
|
|
|
|
|
|
# and remove their current border decorations |
2000
|
|
|
|
|
|
|
# (do we dare to destroy here ???) |
2001
|
|
|
|
|
|
|
# |
2002
|
|
|
|
|
|
|
foreach (@{$this->{PseudoTabs}}) { |
2003
|
|
|
|
|
|
|
next unless $_; |
2004
|
|
|
|
|
|
|
$_->placeForget(); |
2005
|
|
|
|
|
|
|
$_->destroy; |
2006
|
|
|
|
|
|
|
} |
2007
|
|
|
|
|
|
|
delete $this->{PseudoTabs}; |
2008
|
|
|
|
|
|
|
# |
2009
|
|
|
|
|
|
|
# repack the buttonframe |
2010
|
|
|
|
|
|
|
# |
2011
|
|
|
|
|
|
|
$this->{ButtonFrame}->packForget; |
2012
|
|
|
|
|
|
|
$this->{ClientFrame}->packForget; |
2013
|
|
|
|
|
|
|
|
2014
|
|
|
|
|
|
|
$this->{ButtonFrame}->configure($tabsize => 40); |
2015
|
|
|
|
|
|
|
$this->{ButtonFrame}->pack( |
2016
|
|
|
|
|
|
|
-anchor => $tabanchor, |
2017
|
|
|
|
|
|
|
-side => $tabside, |
2018
|
|
|
|
|
|
|
-fill => $tabfill, |
2019
|
|
|
|
|
|
|
); |
2020
|
|
|
|
|
|
|
# |
2021
|
|
|
|
|
|
|
# repack the client frame |
2022
|
|
|
|
|
|
|
# |
2023
|
|
|
|
|
|
|
$this->{ClientFrame}->pack( |
2024
|
|
|
|
|
|
|
-side => $clientside, |
2025
|
|
|
|
|
|
|
-expand => 'true', |
2026
|
|
|
|
|
|
|
-fill => 'both', |
2027
|
|
|
|
|
|
|
); |
2028
|
|
|
|
|
|
|
# |
2029
|
|
|
|
|
|
|
# prep for reconfig |
2030
|
|
|
|
|
|
|
# |
2031
|
|
|
|
|
|
|
$this->{OldWidth} = $this->{ButtonFrame}->reqwidth(); |
2032
|
|
|
|
|
|
|
$this->{OldHeight} = $this->{ButtonFrame}->reqheight(); |
2033
|
|
|
|
|
|
|
# |
2034
|
|
|
|
|
|
|
# recreate our pseudotabs |
2035
|
|
|
|
|
|
|
# |
2036
|
|
|
|
|
|
|
# push @{$this->{PseudoTabs}}, $this->PseudoCreate($_) |
2037
|
|
|
|
|
|
|
# foreach (1..DTF_MAX_ROWS); |
2038
|
|
|
|
|
|
|
# |
2039
|
|
|
|
|
|
|
# finally, redraw everyone |
2040
|
|
|
|
|
|
|
# |
2041
|
|
|
|
|
|
|
$this->TabRedraw(1); |
2042
|
|
|
|
|
|
|
return $oldside; |
2043
|
|
|
|
|
|
|
} |
2044
|
|
|
|
|
|
|
|
2045
|
|
|
|
|
|
|
sub tabscroll { |
2046
|
|
|
|
|
|
|
my ($this, $scroll) = shift; |
2047
|
|
|
|
|
|
|
|
2048
|
|
|
|
|
|
|
return $this->{Scrolled} unless defined($scroll); |
2049
|
|
|
|
|
|
|
return 1 |
2050
|
|
|
|
|
|
|
unless ($this->{Scrolled} ^ $scroll); |
2051
|
|
|
|
|
|
|
# |
2052
|
|
|
|
|
|
|
# set to requested state and redraw |
2053
|
|
|
|
|
|
|
# |
2054
|
|
|
|
|
|
|
$this->{Scrolled} = $scroll; |
2055
|
|
|
|
|
|
|
return $this->TabRedraw(); |
2056
|
|
|
|
|
|
|
} |
2057
|
|
|
|
|
|
|
|
2058
|
|
|
|
|
|
|
sub tabclose { |
2059
|
|
|
|
|
|
|
my ($this, $close) = @_; |
2060
|
|
|
|
|
|
|
|
2061
|
|
|
|
|
|
|
return $this->{Close} unless defined($close); |
2062
|
|
|
|
|
|
|
return 1 unless ($this->{Close} || $close); |
2063
|
|
|
|
|
|
|
|
2064
|
|
|
|
|
|
|
my $clients = $this->{ClientList}; |
2065
|
|
|
|
|
|
|
|
2066
|
|
|
|
|
|
|
if ($this->{Close} && (! $close)) { |
2067
|
|
|
|
|
|
|
# |
2068
|
|
|
|
|
|
|
# remove close buttons from everything |
2069
|
|
|
|
|
|
|
# |
2070
|
|
|
|
|
|
|
delete $this->{Close}; |
2071
|
|
|
|
|
|
|
|
2072
|
|
|
|
|
|
|
$_->[DTF_IDX_FRAME]->Subwidget('CloseBtn')->packForget, |
2073
|
|
|
|
|
|
|
$_->[DTF_IDX_FRAME]->Subwidget('CloseBtn')->Destroy |
2074
|
|
|
|
|
|
|
foreach (@$clients); |
2075
|
|
|
|
|
|
|
} |
2076
|
|
|
|
|
|
|
elsif ($close && (! $this->{Close})) { |
2077
|
|
|
|
|
|
|
# |
2078
|
|
|
|
|
|
|
# add close buttons to everything |
2079
|
|
|
|
|
|
|
# |
2080
|
|
|
|
|
|
|
$this->{Close} = ((ref $close) && (ref $close eq 'CODE')) ? |
2081
|
|
|
|
|
|
|
$close : \&TabRemove; |
2082
|
|
|
|
|
|
|
|
2083
|
|
|
|
|
|
|
$_->[DTF_IDX_FRAME]->Component( |
2084
|
|
|
|
|
|
|
'Button' => 'CloseBtn', |
2085
|
|
|
|
|
|
|
-command => [ $this->{Close}, $this, $_->[DTF_IDX_CAPTION] ], |
2086
|
|
|
|
|
|
|
-anchor => 'ne', |
2087
|
|
|
|
|
|
|
-relief => 'raised', |
2088
|
|
|
|
|
|
|
-borderwidth => 1, |
2089
|
|
|
|
|
|
|
-takefocus => 1, |
2090
|
|
|
|
|
|
|
-padx => 0, |
2091
|
|
|
|
|
|
|
-pady => 0, |
2092
|
|
|
|
|
|
|
-image => $this->{CloseImage} |
2093
|
|
|
|
|
|
|
)->pack( |
2094
|
|
|
|
|
|
|
-side => 'top', |
2095
|
|
|
|
|
|
|
-anchor => 'ne', |
2096
|
|
|
|
|
|
|
-expand => 0, |
2097
|
|
|
|
|
|
|
-fill => 'none', |
2098
|
|
|
|
|
|
|
-ipadx => 0, |
2099
|
|
|
|
|
|
|
-ipady => 0, |
2100
|
|
|
|
|
|
|
-padx => 0, |
2101
|
|
|
|
|
|
|
-pady => 0, |
2102
|
|
|
|
|
|
|
) |
2103
|
|
|
|
|
|
|
foreach (@$clients); |
2104
|
|
|
|
|
|
|
} |
2105
|
|
|
|
|
|
|
else { |
2106
|
|
|
|
|
|
|
# |
2107
|
|
|
|
|
|
|
# reconfig everyone's close button |
2108
|
|
|
|
|
|
|
# |
2109
|
|
|
|
|
|
|
$this->{Close} = ((ref $close) && (ref $close eq 'CODE')) ? |
2110
|
|
|
|
|
|
|
$close : \&TabRemove; |
2111
|
|
|
|
|
|
|
$_->[DTF_IDX_FRAME]->Subwidget('CloseBtn')->configure( |
2112
|
|
|
|
|
|
|
-command => [ $this->{Close}, $this, $_->[DTF_IDX_CAPTION] ]) |
2113
|
|
|
|
|
|
|
foreach (@$clients); |
2114
|
|
|
|
|
|
|
} |
2115
|
|
|
|
|
|
|
return $this->TabRedraw(1); |
2116
|
|
|
|
|
|
|
} |
2117
|
|
|
|
|
|
|
# |
2118
|
|
|
|
|
|
|
# for left/right tabs, we must convert text into |
2119
|
|
|
|
|
|
|
# vertical format |
2120
|
|
|
|
|
|
|
# |
2121
|
|
|
|
|
|
|
sub RotateTabText { |
2122
|
|
|
|
|
|
|
my $text = shift; |
2123
|
|
|
|
|
|
|
my @segments = split /\n/, $text; |
2124
|
|
|
|
|
|
|
my $maxchars = 0; |
2125
|
|
|
|
|
|
|
foreach (@segments) { |
2126
|
|
|
|
|
|
|
$maxchars = length($_) |
2127
|
|
|
|
|
|
|
if ($maxchars < length($_)); |
2128
|
|
|
|
|
|
|
} |
2129
|
|
|
|
|
|
|
|
2130
|
|
|
|
|
|
|
$segments[$_] .= (' ' x ($maxchars - length($segments[$_]))) |
2131
|
|
|
|
|
|
|
foreach (0..$#segments); |
2132
|
|
|
|
|
|
|
|
2133
|
|
|
|
|
|
|
my @lines = ('') x $maxchars; |
2134
|
|
|
|
|
|
|
my @chars; |
2135
|
|
|
|
|
|
|
foreach my $segment (@segments) { |
2136
|
|
|
|
|
|
|
@chars = split('', $segment); |
2137
|
|
|
|
|
|
|
$lines[$_] .= $chars[$_] . ' ' |
2138
|
|
|
|
|
|
|
foreach (0..$#chars); |
2139
|
|
|
|
|
|
|
} |
2140
|
|
|
|
|
|
|
return join("\n", @lines); |
2141
|
|
|
|
|
|
|
} |
2142
|
|
|
|
|
|
|
|
2143
|
|
|
|
|
|
|
sub OnEnter { |
2144
|
|
|
|
|
|
|
my ($widget, $Button, $TabFrame, $Color) = @_; |
2145
|
|
|
|
|
|
|
|
2146
|
|
|
|
|
|
|
$Button->configure( |
2147
|
|
|
|
|
|
|
-bg => $Button->Darken($Button->cget(-bg), 90)); |
2148
|
|
|
|
|
|
|
$TabFrame->configure( |
2149
|
|
|
|
|
|
|
-bg => $TabFrame->Darken($TabFrame->cget(-bg), 90)); |
2150
|
|
|
|
|
|
|
|
2151
|
|
|
|
|
|
|
$TabFrame->bind('' => undef); |
2152
|
|
|
|
|
|
|
$TabFrame->bind('' => undef); |
2153
|
|
|
|
|
|
|
|
2154
|
|
|
|
|
|
|
$Button->bind('' => undef); |
2155
|
|
|
|
|
|
|
$Button->bind('' => undef); |
2156
|
|
|
|
|
|
|
} |
2157
|
|
|
|
|
|
|
|
2158
|
|
|
|
|
|
|
sub OnLeave { |
2159
|
|
|
|
|
|
|
my ($widget, $Button, $TabFrame) = @_; |
2160
|
|
|
|
|
|
|
|
2161
|
|
|
|
|
|
|
#print "Leaving\n"; |
2162
|
|
|
|
|
|
|
|
2163
|
|
|
|
|
|
|
$Button->configure( |
2164
|
|
|
|
|
|
|
-bg => $Button->Darken($Button->cget(-bg), 110)); |
2165
|
|
|
|
|
|
|
$TabFrame->configure( |
2166
|
|
|
|
|
|
|
-bg => $TabFrame->Darken($TabFrame->cget(-bg), 110)); |
2167
|
|
|
|
|
|
|
|
2168
|
|
|
|
|
|
|
$TabFrame->bind('' => [ \&OnEnter, $Button, $TabFrame ]); |
2169
|
|
|
|
|
|
|
$TabFrame->bind('' => undef); |
2170
|
|
|
|
|
|
|
|
2171
|
|
|
|
|
|
|
$Button->bind('' => [ \&OnEnter, $Button, $TabFrame ]); |
2172
|
|
|
|
|
|
|
$Button->bind('' => undef); |
2173
|
|
|
|
|
|
|
} |
2174
|
|
|
|
|
|
|
|
2175
|
|
|
|
|
|
|
sub OnFocusIn { |
2176
|
|
|
|
|
|
|
my ($Button, $TabFrame) = @_; |
2177
|
|
|
|
|
|
|
|
2178
|
|
|
|
|
|
|
print "FocusIn\n"; |
2179
|
|
|
|
|
|
|
|
2180
|
|
|
|
|
|
|
$Button->configure( |
2181
|
|
|
|
|
|
|
-bg => $Button->Darken($Button->cget(-bg), 90)); |
2182
|
|
|
|
|
|
|
$TabFrame->configure( |
2183
|
|
|
|
|
|
|
-bg => $TabFrame->Darken($TabFrame->cget(-bg), 90)); |
2184
|
|
|
|
|
|
|
} |
2185
|
|
|
|
|
|
|
|
2186
|
|
|
|
|
|
|
sub OnFocusOut { |
2187
|
|
|
|
|
|
|
my ($Button, $TabFrame) = @_; |
2188
|
|
|
|
|
|
|
|
2189
|
|
|
|
|
|
|
print "FocusOut\n"; |
2190
|
|
|
|
|
|
|
|
2191
|
|
|
|
|
|
|
$Button->configure( |
2192
|
|
|
|
|
|
|
-bg => $Button->Darken($Button->cget(-bg), 110)); |
2193
|
|
|
|
|
|
|
$TabFrame->configure( |
2194
|
|
|
|
|
|
|
-bg => $TabFrame->Darken($TabFrame->cget(-bg), 110)); |
2195
|
|
|
|
|
|
|
} |
2196
|
|
|
|
|
|
|
|
2197
|
|
|
|
|
|
|
1; |
2198
|
|
|
|
|
|
|
|
2199
|
|
|
|
|
|
|
__END__ |