OK, so here is one for you wxPerl whizzes out there. I really need to figure
this out. I have a derived class which has the following override function for
AutoSizeColumn(). There is also one for AutoSizeRow(), but I’m going to focus
on this one as I believe this is where my issue is occurring. I have a program
which shows a grid which updates every 10 seconds, which includes AutoSize’ing
the grid. Over a period of time, (like say 1 hour), something is happening
which includes a small memory leak, but something more profound with X11. When
the program is quit, it will hang for a while, but only if SMART_AUTOSIZE is
set to 2. If it is zero, or 1 it works fine, but when set to 2 it causes
something to happen that is either a strict memory leak or some excess
chattiness with the X11 server. If used with Exceed on OSX, it will cause it
to lock up the server altogether, to the point it requires to be killed (-9).
The only thing I can see materially different here is that when SMART_AUTOSIZE
is 2, then the current column label is split into words, and the maximum word
width is determined, then WrapColLabelValue() is called which ultimately wraps
the column label value to the width of the column. Any clues?
I’m using WxWidgets 2.8.10
Here is the code:
sub AutoSizeColumn
{
my $self = shift;
my $col = shift;
my $setAsMin = shift;
return if $self->IsColHidden($col);
return $self->SUPER::AutoSizeColumn($col,$setAsMin) unless
$self->{SMART_AUTOSIZE};
my $cwc = defined $self->{COLUMN_WRAP}{$col}{MODE} ? $col : 'ALL';
if ($self->{COL_SIZE}{$col}) {
Debug("fixed col size.. wrapping");
$self->SetColSize($col,$self->{COL_SIZE}{$col});
$self->WrapColumnValues($col) if
$self->{COLUMN_WRAP}{$cwc}{MODE};
return;
}
my $nr = $self->GetNumberRows() - 1;
my $clv = $self->SUPER::GetColLabelValue($col);
my @hdr = $self->{SMART_AUTOSIZE} == 2 ? split(/\s+/,$clv) : ($clv);
if ($hdr[-1] eq '/\\' or $hdr [-1] eq '\\/') {
$hdr[-2] .= ' ' . $hdr[-1];
pop @hdr;
}
my $lfont = $self->GetLabelFont();
my $w = $self->{HIDE_COLUMN_LABEL} ? 0 : Max(map {
($self->GetTextExtent($_,$lfont))[0] } @hdr);
Debug("$col. $clv: w=$w");
for my $r (0..$nr) {
next if $self->IsRowHidden($r);
my $v = $self->{COLUMN_WRAP}{$cwc}{MODE} ?
($self->{COLUMN_WRAP}{$cwc}{WIDTH}
? $self->WrapCellValue($r,$col) :
$self->UnwrapCellValue($r,$col)) : $self->GetCellValue($r,$col);
next unless $v;
$w =
Max($w,($self->GetTextExtent($v,$self->GetCellFont($r,$col)))[0]);
Debug("v='$v' w=$w");
}
if ($w) {
$self->SetColSize($col,$w + GRID_SIZE_PAD);
$self->WrapColLabelValue($col) if $self->{SMART_AUTOSIZE} == 2;
} else {
$self->SUPER::AutoSizeColumn($col,$setAsMin);
}
}
# WrapColLabelValue( <col> )
# If the column has a fixed width, then wrap the Column label contents at
space boundaries to fit.
sub WrapColLabelValue
{
my $self = shift;
my $col = shift;
my $w = $self->GetColSize($col);
my $val = units::unWrapString($self->SUPER::GetColLabelValue($col),1);
return unless $val;
my $font = $self->GetLabelFont();
my ($sx,$sy,$descent,$el) = new
Wx::Window($self,-1)->GetTextExtent($val,$font);
my $nw = int(length($val)/$sx*$w) - 2;
my $sw = units::wrapString($val,'\s+',$nw,1);
$sw =~ s/\n([\/\\]+)$/ $1/;
$self->SUPER::SetColLabelValue($col,$sw);
return 0;
}
# wrapString( <string>, <delimiter>, <width> [, <mode> ] )
# <string> string to be wrapped
# <delimiter> regex expression for delimiter
# <width> max width of the output in characters (string will be
wrapped to not exceed this value)
# <mode> If set, then space delimiters will be compressed (IE: '
' --> ' ').
#
# Returns the wrapped string.
sub wrapString
{
my $str = shift;
my $d = shift;
my $w = shift;
my $mode = shift;
return '' unless defined $str;
my @tok = split /$d/,$str;
my @del = $str =~ /($d)/g;
my $nstr = '';
my $sw = 0;
my $s = $mode ? '\s*' : '';
for my $t (@tok) {
my $d = pop @del;
$d = '' if not defined $d;
$nstr =~ s/$s$/\n/,$sw=0 if $sw and ($sw + length($t.$d)) > $w;
$nstr .= $t.$d;
$sw += length($t.$d);
}
return $nstr;
}
# unWrapString( <string> [, <mode> ] )
# Unwrap the string. If <mode> is set, then add space
# character in place of line feed
sub unWrapString
{
my $str = shift;
my $mode = shift;
my $d = $mode ? ' ' : '';
$str =~ s/\n/$d/g;
return $str;
}
---------------------------------
Jim Clark
Senior Software Engineer, EES
Apple, Inc
408-974-9906 (office)
408-781-1425 (cell)
** Converting pizza into code for over 20 years **