--- deliantra/Deliantra-Client/DC/UI.pm 2006/05/08 22:17:38 1.190 +++ deliantra/Deliantra-Client/DC/UI.pm 2006/05/10 21:12:26 1.193 @@ -234,12 +234,7 @@ } if ($self->{w} != $w || $self->{h} != $h) { - $self->{w} = $w; - $self->{h} = $h; - - $self->size_allocate ($w, $h); - $self->update; - $self->emit (size_allocate => $w, $h); + $CFClient::UI::ROOT->{size_alloc}{$self} = [$self, $w, $h]; } } @@ -258,7 +253,7 @@ for $self->children; $self->check_size; - $self->size_allocate ($self->{w}, $self->{h}); + $CFClient::UI::ROOT->{size_alloc}{$self} = [$self, $self->{w}, $self->{h}]; $self->update; } @@ -269,30 +264,18 @@ delete $self->{max_h}; $self->{max_h} = $h if $h; } -# return top left coordinates -sub _topleft { - my ($self, $x, $y) = @_; - - $self->{parent} - or Carp::confess "no parent widget in _topleft\n";#d# - - $self->{parent}->_topleft ($x + $self->{x}, $y + $self->{y}); -} - # translate global coordinates to local coordinate system sub coord2local { my ($self, $x, $y) = @_; - my ($X, $Y) = $self->_topleft; - ($x - $X, $y - $Y) + $self->{parent}->coord2local ($x - $self->{x}, $y - $self->{y}) } # translate local coordinates to global coordinate system sub coord2global { my ($self, $x, $y) = @_; - my ($X, $Y) = $self->_topleft; - ($x + $X, $y + $Y) + $self->{parent}->coord2global ($x + $self->{x}, $y + $self->{y}) } sub focus_in { @@ -400,71 +383,22 @@ my ($self, $parent) = @_; Scalar::Util::weaken ($self->{parent} = $parent); -} - -sub check_size { - my ($self) = @_; - $self->_check_size; - return; - #TODO: but needs a vastly more difficult algorithm - my $check_size = $CFClient::UI::ROOT->{_check_size} ||= {}; - - $check_size->{$self} = $self; - - $CFClient::UI::ROOT->on_refresh (_check_size => sub { - while (%$check_size) { - my @widgets = values %$check_size; - $_->_check_size - for @widgets; - } - }); + $self->check_size + unless exists $self->{req_w}; } -sub _check_size { +sub check_size { my ($self) = @_; - delete $CFClient::UI::ROOT->{_check_size}{$self}; - - $self->{parent} - or return 1; - - my ($w, $h) = $self->{user_w} && $self->{user_h} - ? @$self{qw(user_w user_h)} - : $self->size_request; - - if ($w != $self->{req_w} || $h != $self->{req_h}) { - $self->{req_w} = $w; - $self->{req_h} = $h; - - $self->{parent}->_check_size - or $self->size_allocate ( - (List::Util::max $self->{w}, $w), - (List::Util::max $self->{h}, $h), - ); - - 1 - } else { - 0 - } + $CFClient::UI::ROOT->{check_size}{$self} = $self; } sub update { my ($self) = @_; - my $update = $CFClient::UI::ROOT->{_update} ||= {}; - - $update->{$self} = $self; - - $CFClient::UI::ROOT->on_refresh (_update => sub { - while (%$update) { - my @widgets = values %$update; - %$update = (); - - $_->{parent} && $_->{parent}->update - for @widgets; - } - }); + $self->{parent}->update + if $self->{parent}; } sub connect { @@ -576,9 +510,7 @@ @{$self->{children}}, @widgets ]; - $_->check_size - for @widgets; - + $self->check_size; $self->update; } @@ -778,11 +710,20 @@ $self->update; } -# hmm, this does not work for topleft of $self... but we should not aks for that -sub _topleft { +# hmm, this does not work for topleft of $self... but we should not ask for that +sub coord2local { + my ($self, $x, $y) = @_; + + $self->SUPER::coord2local ($x + $self->{view_x}, $y + $self->{view_y}) +} + +sub coord2global { my ($self, $x, $y) = @_; - $self->SUPER::_topleft ($x - $self->{view_x}, $y - $self->{view_y}) + $x = List::Util::min $self->{w}, $x - $self->{view_x}; + $y = List::Util::min $self->{h}, $y - $self->{view_y}; + + $self->SUPER::coord2global ($x, $y) } sub find_widget { @@ -1274,6 +1215,8 @@ sub size_allocate { my ($self, $w, $h) = @_; + Carp::confess "negative size" if $w < 0 || $h < 0;#d# + my $children = $self->{children}; my @h = map $_->{req_h}, @$children; @@ -1369,7 +1312,6 @@ $self->{layout}->set_text ($text); - delete $self->{texture}; $self->update; $self->check_size; } @@ -1382,7 +1324,6 @@ $self->{layout}->set_markup ($markup); - delete $self->{texture}; $self->update; $self->check_size; } @@ -2544,7 +2485,7 @@ my %args = @_; - my $item = $args{item}; + my $item = delete $args{item}; my $desc = $item->{nrof} < 2 ? $item->{name} @@ -2583,14 +2524,18 @@ }, %args ); - $self->add(new CFClient::UI::Face + + $self->add (new CFClient::UI::Face can_events => 0, face => $item->{face}, anim => $item->{anim}, - animspeed => $item->{animspeed}); - $self->add(new CFClient::UI::Label + animspeed => $item->{animspeed}, + ); + + $self->add (new CFClient::UI::Label can_events => 0, - text => $desc); + text => $desc, + ); $self } @@ -2627,7 +2572,7 @@ ? $item->{name} : "$item->{nrof} $item->{name_pl}"; - $self->{scrolled}->add (new CFClient::UI::InventoryItem item => $item); + $self->{scrolled}->add ($item->{widget} ||= new CFClient::UI::InventoryItem item => $item); } # $range->{range} = [$self->{pos}, 0, $self->{max_pos}, $page]; @@ -2718,10 +2663,26 @@ use CFClient::OpenGL; +sub new { + my $class = shift; + + $class->SUPER::new ( + @_, + ) +} + +sub configure { + my ($self, $x, $y, $w, $h) = @_; + + $self->{w} = $w; + $self->{h} = $h; +} + sub check_size { my ($self) = @_; - $self->configure (0, 0, $self->{w}, $self->{h}); + $self->size_allocate ($self->{w}, $self->{h}) + if $self->{w}; } sub size_request { @@ -2749,15 +2710,6 @@ } } - $self->{old_w} = $w; - $self->{old_h} = $h; -} - -sub configure { - my ($self, $x, $y, $w, $h) = @_; - - $self->SUPER::configure ($x, $y, $w, $h); - for my $child ($self->children) { my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)}; @@ -2765,9 +2717,18 @@ $Y = List::Util::max 0, List::Util::min $h - $H, $Y; $child->configure ($X, $Y, $W, $H); } + + $self->{old_w} = $w; + $self->{old_h} = $h; } -sub _topleft { +sub coord2local { + my ($self, $x, $y) = @_; + + ($x, $y) +} + +sub coord2global { my ($self, $x, $y) = @_; ($x, $y) @@ -2777,13 +2738,13 @@ my ($self) = @_; $self->check_size; - ::refresh (); + $::WANT_REFRESH++; } sub add { my ($self, $child) = @_; - # integerize window positions + # integerise window positions $child->{x} = int $child->{x}; $child->{y} = int $child->{y}; @@ -2796,11 +2757,56 @@ $self->{refresh_hook}{$id} = $cb; } -sub draw { +sub draw { my ($self) = @_; - while (my $rcb = delete $self->{refresh_hook}) { - $_->() for values %$rcb; + if ($self->{check_size}) { + my @queue = ([], []); + + for (;;) { + if ($self->{check_size}) { + # heuristic: check containers last + push @{ $queue[ ! ! $_->isa ("CFClient::UI::Container") ] }, $_ + for values %{delete $self->{check_size}} + } + + my $widget = (pop @{ $queue[0] }) || (pop @{ $queue[1] }) || last; + + my ($w, $h) = $widget->{user_w} && $widget->{user_h} + ? @$widget{qw(user_w user_h)} + : $widget->size_request; + + if ($w != $widget->{req_w} || $h != $widget->{req_h}) { + Carp::confess "$widget: size_request is negative" if $w < 0 || $h < 0;#d# + + $widget->{req_w} = $w; + $widget->{req_h} = $h; + + $self->{size_alloc}{$widget} = [$widget, $widget->{w}, $widget->{h}]; + + $widget->{parent}->check_size + if $widget->{parent}; + } + } + } + + while ($self->{size_alloc}) { + for (values %{delete $self->{size_alloc}}) { + my ($widget, $w, $h) = @$_; + + $w = 0 if $w < 0; + $h = 0 if $h < 0; + + $widget->{w} = $w; + $widget->{h} = $h; + $widget->size_allocate ($w, $h); + $widget->emit (size_allocate => $w, $h); + } + } + + while ($self->{refresh_hook}) { + $_->() + for values %{delete $self->{refresh_hook}}; } glViewport 0, 0, $::WIDTH, $::HEIGHT;