--- deliantra/Deliantra-Client/DC/UI.pm 2006/05/08 20:39:34 1.186 +++ 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,32 +383,15 @@ my ($self, $parent) = @_; Scalar::Util::weaken ($self->{parent} = $parent); + + $self->check_size + unless exists $self->{req_w}; } sub check_size { my ($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 { @@ -532,18 +498,19 @@ } sub add { - my ($self, $child) = @_; + my ($self, @widgets) = @_; - $child->set_parent ($self); + $_->set_parent ($self) + for @widgets; use sort 'stable'; $self->{children} = [ sort { $a->{z} <=> $b->{z} } - @{$self->{children}}, $child + @{$self->{children}}, @widgets ]; - $child->check_size; + $self->check_size; $self->update; } @@ -743,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 { @@ -1239,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; @@ -1334,7 +1312,6 @@ $self->{layout}->set_text ($text); - delete $self->{texture}; $self->update; $self->check_size; } @@ -1347,7 +1324,6 @@ $self->{layout}->set_markup ($markup); - delete $self->{texture}; $self->update; $self->check_size; } @@ -2509,7 +2485,7 @@ my %args = @_; - my $item = $args{item}; + my $item = delete $args{item}; my $desc = $item->{nrof} < 2 ? $item->{name} @@ -2548,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 } @@ -2592,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]; @@ -2683,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 { @@ -2704,7 +2700,7 @@ if ($old_w && $old_h) { for my $child ($self->children) { $child->{x} = int 0.5 + $child->{x} * $w / $old_w; - $child->{w} = int 0.5 + $child->{req_w} * $w / $old_w; + $child->{w} = int 0.5 + $child->{w} * $w / $old_w; $child->{req_w} = int 0.5 + $child->{req_w} * $w / $old_w if exists $child->{req_w}; $child->{user_w} = int 0.5 + $child->{user_w} * $w / $old_w if exists $child->{user_w}; $child->{y} = int 0.5 + $child->{y} * $h / $old_h; @@ -2714,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)}; @@ -2730,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 coord2local { + my ($self, $x, $y) = @_; + + ($x, $y) } -sub _topleft { +sub coord2global { my ($self, $x, $y) = @_; ($x, $y) @@ -2742,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}; @@ -2761,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;