#!/usr/local/bin/perl -w
use
vars
qw($VERSION @ISA)
;
@ISA
=
qw(Tk::Toplevel)
;
Construct Tk::Widget
'FontDialog'
;
$VERSION
=
'0.08'
;
sub
Populate {
my
(
$w
,
$args
) =
@_
;
$w
->SUPER::Populate(
$args
);
$w
->protocol(
'WM_DELETE_WINDOW'
=> [
'Cancel'
,
$w
]);
$w
->withdraw;
if
(
exists
$args
->{-font}) {
$w
->optionAdd(
'*font'
=>
delete
$args
->{-font});
}
my
$dialog_font
;
my
$font_name
=
$w
->optionGet(
"font"
,
"*"
);
if
(!
defined
$font_name
) {
my
$l
=
$w
->Label;
$dialog_font
=
$w
->fontCreate(
$w
->fontActual(
$l
->cget(-font)));
$l
->destroy;
}
else
{
$dialog_font
=
$w
->fontCreate(
$w
->fontActual(
$font_name
));
}
if
(
exists
$args
->{-initfont}) {
$w
->{
'curr_font'
} =
$w
->fontCreate(
$w
->fontActual
(
delete
$args
->{-initfont}));
}
else
{
$w
->{
'curr_font'
} =
$dialog_font
;
}
my
$bold_font
=
$w
->fontCreate(
$w
->fontActual(
$dialog_font
),
-weight
=>
'bold'
);
my
$italic_font
=
$w
->fontCreate(
$w
->fontActual(
$dialog_font
),
-slant
=>
'italic'
);
my
$underline_font
=
$w
->fontCreate(
$w
->fontActual(
$dialog_font
),
-underline
=> 1);
my
$overstrike_font
=
$w
->fontCreate(
$w
->fontActual(
$dialog_font
),
-overstrike
=> 1);
my
$f1
=
$w
->Frame->
pack
(
-expand
=> 1,
-fill
=>
'both'
,
-padx
=> 2,
-pady
=> 2);
my
$ffam
=
$f1
->Frame->
pack
(
-expand
=> 1,
-fill
=>
'both'
,
-side
=>
'left'
);
my
$fsize
=
$f1
->Frame->
pack
(
-expand
=> 1,
-fill
=>
'both'
,
-side
=>
'left'
);
my
$fstyle
=
$f1
->Frame->
pack
(
-expand
=> 1,
-fill
=>
'both'
,
-side
=>
'left'
);
my
(
%family_res
) = _get_label(
delete
$args
->{
'-familylabel'
}
||
'~Family:'
);
$ffam
->Label
(@{
$family_res
{
'args'
}},
-font
=>
$bold_font
,
)->
pack
(
-anchor
=>
'w'
);
my
$famlb
=
$ffam
->Scrolled
(
'HList'
,
-scrollbars
=>
'osoe'
,
-selectmode
=>
'single'
,
-bg
=>
'white'
,
-browsecmd
=>
sub
{
my
$family
=
$w
->{
'family_index'
}[
$_
[0]];
$w
->UpdateFont(
-family
=>
$family
)
},
)->
pack
(
-expand
=> 1,
-fill
=>
'both'
,
-anchor
=>
'w'
);
$w
->Advertise(
'family_list'
=>
$famlb
);
my
(
%size_res
) = _get_label(
delete
$args
->{
'-sizelabel'
}
||
'~Size:'
);
$fsize
->Label
(@{
$size_res
{
'args'
}},
-font
=>
$bold_font
,
)->
pack
(
-anchor
=>
'w'
);
my
$sizelb
=
$fsize
->Scrolled
(
'HList'
,
-scrollbars
=>
'oe'
,
-width
=> 3,
-bg
=>
'white'
,
-selectmode
=>
'single'
,
-browsecmd
=>
sub
{
$w
->UpdateFont(
-size
=>
$_
[0]) },
)->
pack
(
-expand
=> 1,
-fill
=>
'both'
,
-anchor
=>
'w'
);
$w
->Advertise(
'size_list'
=>
$sizelb
);
$sizelb
->
bind
(
"<3>"
=> [
$w
,
'_custom_size'
]);
my
@fontsizes
;
if
(
exists
$args
->{-fontsizes}) {
@fontsizes
= @{
delete
$args
->{-fontsizes} };
}
else
{
@fontsizes
=
qw(0 2 3 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
23 24 25 26 27 28 29 30 33 34 36 40 44 48 50 56 64 72)
;
}
my
$curr_size
=
$w
->fontActual(
$w
->{
'curr_font'
}, -size);
foreach
my
$size
(
@fontsizes
) {
$sizelb
->add(
$size
,
-text
=>
$size
);
if
(
$size
==
$curr_size
) {
$sizelb
->selectionSet(
$size
);
$sizelb
->anchorSet(
$size
);
$sizelb
->see(
$size
);
}
}
$fstyle
->Label->
pack
;
my
$fstyle2
=
$fstyle
->Frame->
pack
(
-expand
=> 1,
-fill
=>
'both'
,
-side
=>
'left'
);
my
(
%weight_res
) = _get_label(
delete
$args
->{-weightlabel}
||
'~Bold'
);
my
$weight
=
$w
->fontActual(
$w
->{
'curr_font'
}, -weight);
my
$wcb
=
$fstyle2
->Checkbutton
(
-variable
=> \
$weight
,
-font
=>
$bold_font
,
-onvalue
=>
'bold'
,
-offvalue
=>
'normal'
,
@{
$weight_res
{
'args'
}},
-command
=>
sub
{
$w
->UpdateFont(
-weight
=>
$weight
) }
)->
pack
(
-anchor
=>
'w'
,
-expand
=> 1);
my
(
%slant_res
) = _get_label(
delete
$args
->{-slantlabel}
||
'~Italic'
);
my
$slant
=
$w
->fontActual(
$w
->{
'curr_font'
}, -slant);
my
$scb
=
$fstyle2
->Checkbutton
(
-variable
=> \
$slant
,
-font
=>
$italic_font
,
-onvalue
=>
'italic'
,
-offvalue
=>
'roman'
,
@{
$slant_res
{
'args'
}},
-command
=>
sub
{
$w
->UpdateFont(
-slant
=>
$slant
) }
)->
pack
(
-anchor
=>
'w'
,
-expand
=> 1);
my
(
%underline_res
) = _get_label(
delete
$args
->{-underlinelabel}
||
'~Underline'
);
my
$underline
=
$w
->fontActual(
$w
->{
'curr_font'
}, -underline);
my
$ucb
=
$fstyle2
->Checkbutton
(
-variable
=> \
$underline
,
-font
=>
$underline_font
,
-onvalue
=> 1,
-offvalue
=> 0,
@{
$underline_res
{
'args'
}},
-command
=>
sub
{
$w
->UpdateFont(
-underline
=>
$underline
) }
)->
pack
(
-anchor
=>
'w'
,
-expand
=> 1);
my
(
%overstrike_res
) = _get_label(
delete
$args
->{-overstrikelabel}
||
'O~verstrike'
);
my
$overstrike
=
$w
->fontActual(
$w
->{
'curr_font'
}, -overstrike);
my
$ocb
=
$fstyle2
->Checkbutton
(
-variable
=> \
$overstrike
,
-font
=>
$overstrike_font
,
-onvalue
=> 1,
-offvalue
=> 0,
@{
$overstrike_res
{
'args'
}},
-command
=>
sub
{
$w
->UpdateFont(
-overstrike
=>
$overstrike
) }
)->
pack
(
-anchor
=>
'w'
,
-expand
=> 1);
my
$c
=
$w
->Canvas
(
-height
=> 36,
-bg
=>
'white'
,
-relief
=>
'sunken'
,
-bd
=> 2,
)->
pack
(
-expand
=> 1,
-fill
=>
'both'
,
-padx
=> 3,
-pady
=> 3);
$w
->Advertise(
'sample_canvas'
=>
$c
);
my
$bf
=
$w
->Frame->
pack
(
-fill
=>
'x'
,
-padx
=> 3,
-pady
=> 3);
my
(
%ok_res
) = _get_label(
delete
$args
->{
'-oklabel'
}
||
"~OK"
);
my
$okb
=
$bf
->Button
(@{
$ok_res
{
'args'
}},
-fg
=>
'green4'
,
-font
=>
$bold_font
,
-command
=> [
'Accept'
,
$w
],
)->grid(
-column
=> 0,
-row
=> 0,
-rowspan
=> 2,
-sticky
=>
'ew'
,
-padx
=> 5);
my
(
%apply_res
) = _get_label(
delete
$args
->{
'-applylabel'
}
||
"~Apply"
);
my
$applyb
;
if
(
$args
->{-applycmd}) {
my
$applycmd
=
delete
$args
->{-applycmd};
$applyb
=
$bf
->Button
(@{
$apply_res
{
'args'
}},
-fg
=>
'yellow4'
,
-font
=>
$bold_font
,
-command
=>
sub
{
$applycmd
->(
$w
->ReturnFont(
$w
->{
'curr_font'
})) },
)->grid(
-column
=> 1,
-row
=> 0,
-rowspan
=> 2,
-sticky
=>
'ew'
,
-padx
=> 5);
}
my
(
%cancel_res
) = _get_label(
delete
$args
->{
'-cancellabel'
}
||
"~Cancel"
);
my
$cancelb
=
$bf
->Button
(@{
$cancel_res
{
'args'
}},
-fg
=>
'red'
,
-font
=>
$bold_font
,
-command
=> [
'Cancel'
,
$w
],
)->grid(
-column
=> 2,
-row
=> 0,
-rowspan
=> 2,
-sticky
=>
'ew'
,
-padx
=> 5);
$bf
->grid(
'columnconfigure'
, 3,
-weight
=> 1.0);
my
(
%altsample_res
) = _get_label(
delete
$args
->{
'-altsamplelabel'
}
||
"A~lt sample"
);
my
$altcb
=
$bf
->Checkbutton
(@{
$altsample_res
{
'args'
}},
-variable
=> \
$w
->{
'alt_sample'
},
-command
=>
sub
{
$w
->UpdateFont; },
)->grid(
-column
=> 4,
-row
=> 0,
-sticky
=>
'w'
,
-padx
=> 5);
my
(
%nicefonts_res
,
$nicecb
);
if
(!
exists
$args
->{
'-nicefontsbutton'
} ||
$args
->{
'-nicefontsbutton'
}) {
%nicefonts_res
= _get_label(
delete
$args
->{
'-nicefontslabel'
}
||
"~Nicefonts"
);
$nicecb
=
$bf
->Checkbutton
(@{
$nicefonts_res
{
'args'
}},
-variable
=> \
$w
->{Configure}{-nicefont},
-command
=>
sub
{
$w
->InsertFamilies; },
)->grid(
-column
=> 4,
-row
=> 1,
-sticky
=>
'w'
,
-padx
=> 5);
}
delete
$args
->{
'-nicefontsbutton'
};
my
(
%fixedfonts_res
,
$fixedcb
);
if
(!
exists
$args
->{
'-fixedfontsbutton'
} ||
$args
->{
'-fixedfontsbutton'
}) {
%fixedfonts_res
= _get_label(
delete
$args
->{
'-fixedfontslabel'
}
||
"Fi~xed Only"
);
$fixedcb
=
$bf
->Checkbutton
(@{
$fixedfonts_res
{
'args'
}},
-variable
=> \
$w
->{Configure}{-fixedfont},
-command
=>
sub
{
$w
->InsertFamilies; },
)->grid(
-column
=> 5,
-row
=> 0,
-sticky
=>
'w'
,
-padx
=> 5);
}
delete
$args
->{
'-fixedfontsbutton'
};
$w
->grid(
'columnconfigure'
, 0,
-minsize
=> 4);
$w
->grid(
'columnconfigure'
, 4,
-minsize
=> 4);
$w
->grid(
'rowconfigure'
, 0,
-minsize
=> 4);
$w
->grid(
'rowconfigure'
, 8,
-minsize
=> 4);
$w
->
bind
(
"<$family_res{'key'}>"
=>
sub
{
$famlb
->focus })
if
$family_res
{
'key'
};
$w
->
bind
(
"<$size_res{'key'}>"
=>
sub
{
$sizelb
->focus })
if
$size_res
{
'key'
};
$w
->
bind
(
"<$weight_res{'key'}>"
=>
sub
{
$wcb
->invoke })
if
$weight_res
{
'key'
};
$w
->
bind
(
"<$slant_res{'key'}>"
=>
sub
{
$scb
->invoke })
if
$slant_res
{
'key'
};
$w
->
bind
(
"<$underline_res{'key'}>"
=>
sub
{
$ucb
->invoke })
if
$underline_res
{
'key'
};
$w
->
bind
(
"<$overstrike_res{'key'}>"
=>
sub
{
$ocb
->invoke })
if
$overstrike_res
{
'key'
};
$w
->
bind
(
"<$ok_res{'key'}>"
=>
sub
{
$okb
->invoke })
if
$ok_res
{
'key'
};
$w
->
bind
(
"<Return>"
=>
sub
{
$okb
->invoke });
$w
->
bind
(
"<$apply_res{'key'}>"
=>
sub
{
$applyb
->invoke })
if
$applyb
&&
$apply_res
{
'key'
};
$w
->
bind
(
"<$cancel_res{'key'}>"
=>
sub
{
$cancelb
->invoke })
if
$cancel_res
{
'key'
};
$w
->
bind
(
"<Escape>"
=>
sub
{
$cancelb
->invoke });
$w
->
bind
(
"<$altsample_res{'key'}>"
=>
sub
{
$altcb
->invoke })
if
$altsample_res
{
'key'
};
$w
->
bind
(
"<$nicefonts_res{'key'}>"
=>
sub
{
$nicecb
->invoke })
if
$nicefonts_res
{
'key'
};
$w
->
bind
(
"<$fixedfonts_res{'key'}>"
=>
sub
{
$fixedcb
->invoke })
if
$fixedfonts_res
{
'key'
};
$w
->ConfigSpecs
(
-subbg
=> [
'PASSIVE'
,
'subBackground'
,
'SubBackground'
,
'white'
],
-nicefont
=> [
'PASSIVE'
,
undef
,
undef
, 0],
-fixedfont
=> [
'PASSIVE'
,
undef
,
undef
, 0],
-sampletext
=> [
'PASSIVE'
,
undef
,
undef
,
'The Quick Brown Fox Jumps Over The Lazy Dog.'
],
-title
=> [
'METHOD'
,
undef
,
undef
,
'Choose font'
],
-customsizetitle
=> [
'PASSIVE'
,
undef
,
undef
,
'Choose font size'
],
DEFAULT
=> [
'family_list'
],
);
$w
->Delegates(
DEFAULT
=>
'family_list'
);
$w
;
}
sub
UpdateFont {
my
(
$w
,
%args
) =
@_
;
$w
->fontConfigure(
$w
->{
'curr_font'
},
%args
)
if
scalar
%args
;
my
$c
=
$w
->Subwidget(
'sample_canvas'
);
$c
->
delete
(
'font'
);
eval
{
my
$sampletext
;
my
$ch_width
=
$w
->fontMeasure(
$w
->{
'curr_font'
},
'M'
);
my
$ch_height
=
$w
->fontMetrics(
$w
->{
'curr_font'
}, -linespace);
if
(
$w
->{
'alt_sample'
}) {
my
$x
;
my
$y
= 4;
for
(
my
$i
= 32;
$i
< 256;
$i
+=16) {
$x
= 4;
for
my
$j
(0 .. 15) {
next
if
$i
+
$j
== 127;
my
$ch
=
chr
(
$i
+
$j
);
unless
(
$ch
eq
"\r"
||
$ch
eq
"\n"
) {
$c
->createText(
$x
,
$y
,
-anchor
=>
'nw'
,
-text
=>
$ch
,
-font
=>
$w
->{
'curr_font'
},
-tags
=>
'font'
);
}
$x
+=
$ch_width
+ 4;
}
$y
+=
$ch_height
;
}
}
else
{
$c
->createText(4, 4,
-anchor
=>
'nw'
,
-text
=>
$w
->cget(-sampletext),
-font
=>
$w
->{
'curr_font'
},
-tags
=>
'font'
);
}
};
warn
$@
if
$@;
}
sub
Cancel {
my
$w
=
shift
;
$w
->{Selected} =
undef
;
}
sub
Accept {
my
$w
=
shift
;
$w
->{Selected} =
$w
->{
'curr_font'
};
}
sub
Show {
my
(
$w
,
%args
) =
@_
;
my
$test_hack
=
delete
$args
{
'-_testhack'
};
$w
->transient(
$w
->Parent->toplevel);
my
$oldFocus
=
$w
->focusCurrent;
my
$oldGrab
=
$w
->grab(
'current'
);
my
$grabStatus
=
$oldGrab
->grab(
'status'
)
if
(
$oldGrab
);
$w
->grab;
$w
->InsertFamilies();
$w
->UpdateFont();
$w
->Subwidget(
'family_list'
)->configure(
-bg
=>
$w
->cget(-subbg));
$w
->Subwidget(
'size_list'
)->configure(
-bg
=>
$w
->cget(-subbg));
$w
->Subwidget(
'sample_canvas'
)->configure(
-bg
=>
$w
->cget(-subbg));
$w
->Popup(
%args
);
$w
->focus;
$w
->waitVariable(\
$w
->{Selected})
unless
$test_hack
;
eval
{
$oldFocus
->focus
if
$oldFocus
;
};
$w
->grab(
'release'
);
$w
->withdraw;
if
(
$oldGrab
) {
if
(
$grabStatus
eq
'global'
) {
$oldGrab
->grab(
'-global'
);
}
else
{
$oldGrab
->grab;
}
}
$w
->ReturnFont(
$w
->{Selected});
}
sub
ReturnFont {
my
(
$w
,
$var
) =
@_
;
if
(
defined
$var
) {
my
$ret
=
$w
->fontCreate(
$w
->font(
'actual'
,
$var
));
$ret
;
}
else
{
undef
;
}
}
sub
InsertFamilies {
my
$w
=
shift
;
my
$old_cursor
=
$w
->cget(-cursor);
$w
->configure(
-cursor
=>
'watch'
);
$w
->idletasks;
eval
{
$w
->{
'family_index'
} = [];
my
$nicefont
=
$w
->cget(-nicefont);
my
$fixedfont
=
$w
->cget(-fixedfont);
my
$curr_family
=
$w
->fontActual(
$w
->{
'curr_font'
}, -family);
my
$famlb
=
$w
->Subwidget(
'family_list'
);
$famlb
->
delete
(
'all'
);
my
@fam
=
sort
$w
->fontFamilies;
my
$bg
=
$w
->cget(-subbg);
my
$i
= 0;
foreach
my
$fam
(
@fam
) {
next
if
$fam
eq
''
;
next
if
$fixedfont
and not
$w
->fontMetrics(
$w
->Font(
-family
=>
$fam
),
'-fixed'
);
(
my
$u_fam
=
$fam
) =~ s/\b(.)/\u$1/g;
$w
->{
'family_index'
}[
$i
] =
$fam
;
my
$f_style
=
$famlb
->ItemStyle
(
'text'
,
(
$nicefont
? (
-font
=>
"{$fam}"
) : ()),
-background
=>
$bg
,
);
$famlb
->add(
$i
,
-text
=>
$u_fam
,
-style
=>
$f_style
);
if
(
$curr_family
eq
$fam
) {
$famlb
->selectionSet(
$i
);
$famlb
->anchorSet(
$i
);
$famlb
->see(
$i
);
}
$i
++;
}
};
warn
$@
if
$@;
$w
->configure(
-cursor
=>
$old_cursor
);
}
sub
_get_label {
my
$s
=
shift
;
my
%res
;
if
(
$s
=~ s/(.*)~(.)/$1$2/) {
my
$key
=
lc
($2);
my
$underline
=
length
($1);
@{
$res
{
'args'
}} = (
-text
=>
$s
,
-underline
=>
$underline
);
$res
{
'key'
} =
$key
;
}
else
{
@{
$res
{
'args'
}} = (
-text
=>
$s
);
}
%res
;
}
sub
_custom_size {
my
(
$w
) =
@_
;
my
$t
=
$w
->Toplevel;
my
$label
=
$w
->cget(-customsizetitle);
$t
->title(
$label
);
my
$sizelb
=
$w
->Subwidget(
"size_list"
);
my
$fontsize
= 10;
if
(
defined
$sizelb
->info(
"selection"
)) {
$fontsize
=
$sizelb
->entrycget(
$sizelb
->info(
"selection"
), -text);
}
my
$f1
=
$t
->Frame->
pack
;
$f1
->Label(
-text
=>
$label
)->
pack
(
-side
=>
'left'
);
my
$e
=
$f1
->Entry(
-width
=> 4,
-textvariable
=> \
$fontsize
)->
pack
(
-side
=>
"left"
);
$e
->focus;
$e
->selectionRange(0,
'end'
);
$e
->icursor(
'end'
);
my
$f
=
$t
->Frame->
pack
;
my
$waitvar
= 0;
my
$ok
=
$f
->Button
(
-text
=>
"Ok"
,
-command
=>
sub
{
$w
->UpdateFont(
-size
=>
$fontsize
);
$sizelb
->selectionClear;
$sizelb
->anchorClear;
foreach
(
$sizelb
->info(
"children"
)) {
if
(
$sizelb
->entrycget(
$_
, -text) eq
$fontsize
) {
$sizelb
->selectionSet(
$_
);
$sizelb
->anchorSet(
$_
);
$sizelb
->see(
$_
);
last
;
}
}
$waitvar
= 1;
})->
pack
(
-side
=>
"left"
);
$f
->Button(
-text
=>
"Cancel"
,
-command
=>
sub
{
$waitvar
= -1 })->
pack
(
-side
=>
"left"
);
$e
->
bind
(
"<Return>"
=>
sub
{
$ok
->invoke });
$t
->Popup(
-popover
=>
"cursor"
);
$t
->waitVariable(\
$waitvar
);
$t
->destroy;
}
package
Tk::Widget;
sub
RefontTree {
my
(
$w
,
%args
) =
@_
;
my
$dbOption
;
my
$value
;
my
$font
=
$args
{-font} or
die
"No font specified"
;
eval
{
local
$SIG
{
'__DIE__'
};
$value
=
$w
->cget(-font) };
if
(
defined
$value
) {
$w
->configure(
-font
=>
$font
);
}
if
(
$w
->isa(
'Tk::Canvas'
) and
$args
{-canvas}) {
foreach
my
$item
(
$w
->find(
'all'
)) {
eval
{
local
$SIG
{
'__DIE__'
};
$value
=
$w
->itemcget(
$item
, -font) };
if
(
defined
$value
) {
$w
->itemconfigure(
$item
,
-font
=>
$font
);
}
}
}
foreach
my
$child
(
$w
->children) {
$child
->RefontTree(
%args
);
}
}
1;