--- deliantra/Deliantra-Client/DC/UI.pm 2007/07/16 12:36:48 1.374 +++ deliantra/Deliantra-Client/DC/UI.pm 2007/07/17 17:39:07 1.380 @@ -946,6 +946,8 @@ package CFPlus::UI::ViewPort; +use List::Util qw(min max); + our @ISA = CFPlus::UI::Window::; sub new { @@ -986,10 +988,16 @@ sub set_offset { my ($self, $x, $y) = @_; - $self->{view_x} = int $x; - $self->{view_y} = int $y; + my $x = max 0, min $self->child->{w} - $self->{w}, int $x; + my $y = max 0, min $self->child->{h} - $self->{h}, int $y; - $self->update; + if ($x != $self->{view_x} or $y != $self->{view_y}) { + $self->{view_x} = $x; + $self->{view_y} = $y; + + $self->emit (changed => $x, $y); + $self->update; + } } # hmm, this does not work for topleft of $self... but we should not ask for that @@ -1074,9 +1082,17 @@ ); $self->{vp} = new CFPlus::UI::ViewPort - expand => 1, - scroll_x => $self->{scroll_x}, - scroll_y => $self->{scroll_y}, + expand => 1, + scroll_x => $self->{scroll_x}, + scroll_y => $self->{scroll_y}, + on_changed => sub { + my ($vp, $x, $y) = @_; + + $vp->{parent}{hslider}->set_value ($x); + $vp->{parent}{vslider}->set_value ($y); + + 0 + }, ; $self->SUPER::add (0, 0, $self->{vp}); @@ -1094,16 +1110,6 @@ $self->{vp}->add ($self->{child} = $widget); } -sub invoke_mouse_wheel { - my ($self, $ev) = @_; - - return 0 unless $ev->{dy}; # only vertical movements for now - - $self->{vslider}->emit (mouse_wheel => $ev); - - 1 -} - sub update_slider { my ($self) = @_; @@ -1135,6 +1141,59 @@ $self->update_slider; } +sub invoke_mouse_wheel { + my ($self, $ev) = @_; + + return 0 unless $ev->{dy}; # only vertical movements for now + + $self->{vslider}->emit (mouse_wheel => $ev); + + 1 +} + +sub invoke_button_down { + my ($self, $ev, $x, $y) = @_; + + if ($ev->{button} == 2) { + $self->grab_focus; + + my $ox = $self->{vp}{view_x} + $ev->{x}; + my $oy = $self->{vp}{view_y} + $ev->{y}; + + $self->{motion} = sub { + my ($ev, $x, $y) = @_; + + $self->{vp}->set_offset ($ox - $ev->{x}, $oy - $ev->{y}); + $self->update; + }; + + return 1; + } + + 0 +} + +sub invoke_button_up { + my ($self, $ev, $x, $y) = @_; + + if (delete $self->{motion}) { + return 1; + } + + 0 +} + +sub invoke_mouse_motion { + my ($self, $ev, $x, $y) = @_; + + if ($self->{motion}) { + $self->{motion}->($ev, $x, $y); + return 1; + } + + 0 +} + sub invoke_size_allocate { my ($self, $w, $h) = @_; @@ -3436,25 +3495,45 @@ if ($self->{anim} && $self->{animspeed}) { CFPlus::weaken (my $widget = $self); + $widget->{animspeed} = List::Util::max 0.05, $widget->{animspeed}; + $widget->{anim_start} = $self->{animspeed} * Event::time / $self->{animspeed}; $self->{timer} = Event->timer ( - at => $self->{animspeed} * int $::NOW / $self->{animspeed}, - hard => 1, - interval => $self->{animspeed}, + parked => 1, cb => sub { - return unless $::CONN; + return unless $::CONN && $widget; ++$widget->{frame}; - $self->update_face; - $self->update; + $widget->update_face; + $widget->update; + + $widget->update_timer; }, ); $self->update_face; + $self->update_timer; } $self } +sub update_timer { + my ($self) = @_; + + return unless $self->{timer}; + + if ($self->{visible}) { + $self->{timer}->at ( + $self->{anim_start} + + $self->{animspeed} + * int 1.5 + (Event::time - $self->{anim_start}) / $self->{animspeed} + ); + $self->{timer}->start; + } else { + $self->{timer}->stop; + } +} + sub update_face { my ($self) = @_; @@ -3494,6 +3573,14 @@ $self->SUPER::update; } +sub invoke_visibility_change { + my ($self) = @_; + + $self->update_timer; + + 0 +} + sub _draw { my ($self) = @_; @@ -3518,7 +3605,7 @@ sub destroy { my ($self) = @_; - $self->{timer}->cancel + (delete $self->{timer})->cancel if $self->{timer}; $self->SUPER::destroy;