| 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__ |