--- deliantra/Deliantra-Client/DC/UI.pm 2006/05/25 16:35:42 1.235 +++ deliantra/Deliantra-Client/DC/UI.pm 2006/05/27 21:15:57 1.245 @@ -7,15 +7,35 @@ use List::Util (); use CFClient; +use CFClient::Texture; our ($FOCUS, $HOVER, $GRAB); # various widgets +our $LAYOUT; our $ROOT; our $TOOLTIP; our $BUTTON_STATE; our %WIDGET; # all widgets, weak-referenced +sub get_layout { + for (grep { $_->{name} } values %WIDGET) { + $LAYOUT->{$_->{name}} = { + x => $_->{x} / $::WIDTH, + y => $_->{y} / $::HEIGHT, + w => $_->{w} / $::WIDTH, + h => $_->{h} / $::HEIGHT + }; + } + + return $LAYOUT; +} + +sub set_layout { + my ($layout) = @_; + $LAYOUT = $layout; +} + sub check_tooltip { if (!$GRAB) { for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) { @@ -188,16 +208,33 @@ }, $class; for (keys %$self) { - if (/^connect_(.*)$/) { + if (/^on_(.*)$/) { $self->connect ($1 => delete $self->{$_}); } } Scalar::Util::weaken ($CFClient::UI::WIDGET{$self+0} = $self); + if (my $layout = $CFClient::UI::LAYOUT->{$self->{name}}) { + $self->{user_x} = $layout->{x} * $::WIDTH; + $self->{user_y} = $layout->{y} * $::HEIGHT; + $self->{user_w} = ($layout->{w} != 0 ? $layout->{w} : 1) * $::WIDTH; + $self->{user_h} = ($layout->{h} != 0 ? $layout->{h} : 1) * $::HEIGHT; + } + $self } +sub toggle_visibility { + my ($self) = @_; + + if ($self->{visible}) { + $self->hide; + } else { + $self->show; + } +} + sub destroy { my ($self) = @_; @@ -228,8 +265,11 @@ sub set_invisible { my ($self) = @_; + return unless $self->{visible}; + # broken show/hide model + delete $self->{root}; delete $self->{visible}; undef $GRAB if $GRAB == $self; @@ -239,6 +279,8 @@ if $CFClient::UI::TOOLTIP->{owner} == $self; $self->focus_out; + + $self->emit (visibility_change => 0); } sub hide { @@ -460,6 +502,14 @@ Scalar::Util::weaken ($self->{parent} = $parent); + if ($parent->{visible} || 1) { + $self->{root} = $parent->{root}; + $self->{visible} = $parent->{visible} + 1; + + $self->emit (visibility_change => 1) + unless $self->{parent}{visible}; + } + # TODO: req_w _does_change after ->reconfigure $self->check_size unless exists $self->{req_w}; @@ -500,6 +550,10 @@ || $self->$signal (@args); } +sub visibility_change { + #my ($self, $visible) = @_; +} + sub DESTROY { my ($self) = @_; @@ -620,7 +674,7 @@ $self->{children} = [ grep $_ != $child, @{ $self->{children} } ]; - $self->check_size; + $self->check_size (1); $self->update; } @@ -855,9 +909,9 @@ my $self; my $slider = new CFClient::UI::Slider - vertical => 1, - range => [0, 0, 1, 0.01], # HACK fix - connect_changed => sub { + vertical => 1, + range => [0, 0, 1, 0.01], # HACK fix + on_changed => sub { $self->{vp}->set_offset (0, $_[1]); }, ; @@ -875,6 +929,16 @@ $self } +sub update { + my ($self) = @_; + + $self->SUPER::update; + + # todo: overwrite size_allocate of child + my $child = $self->{vp}->child; + $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]); +} + sub size_allocate { my ($self, $w, $h) = @_; @@ -1012,9 +1076,11 @@ my $dx = $ev->{x} - $ox; my $dy = $ev->{y} - $oy; + $self->{user_x} = $wx + $dx * $mx; + $self->{user_y} = $wy + $dy * $my; $self->{user_w} = $bw + $dx * ($mx ? -1 : 1); $self->{user_h} = $bh + $dy * ($my ? -1 : 1); - $self->move ($wx + $dx * $mx, $wy + $dy * $my); + $self->move ($self->{user_x}, $self->{user_y}); $self->check_size; }; @@ -1027,7 +1093,9 @@ ($x, $y) = ($ev->{x}, $ev->{y}); - $self->move ($bx + $x - $ox, $by + $y - $oy); + $self->{user_x} = $bx + $x - $ox; + $self->{user_y} = $by + $y - $oy; + $self->move ($self->{user_x}, $self->{user_y}); $self->update; }; } @@ -1103,20 +1171,20 @@ ) } +sub children { + grep $_, map @$_, grep $_, @{ $_[0]{children} } +} + sub add { my ($self, $x, $y, $child) = @_; $child->set_parent ($self); $self->{children}[$y][$x] = $child; - $child->check_size; -} - -sub children { - grep $_, map @$_, grep $_, @{ $_[0]{children} } + $self->check_size (1); } -# TODO: move to container class maybe? send childs a signal on removal? +# TODO: move to container class maybe? send children a signal on removal? sub clear { my ($self) = @_; @@ -1128,6 +1196,7 @@ $_->hide; } + $self->check_size (1); $self->update; } @@ -1169,8 +1238,8 @@ my ($ws, $hs) = $self->get_wh; - my $req_w = sum @$ws; - my $req_h = sum @$hs; + my $req_w = (sum @$ws) || 1; + my $req_h = (sum @$hs) || 1; # TODO: nicer code && do row_expand my @col_expand = @{$self->{col_expand}}; @@ -2134,9 +2203,10 @@ sub set_range { my ($self, $range) = @_; - $self->{range} = $range; + ($range, $self->{range}) = ($self->{range}, $range); - $self->update; + $self->update + if "@$range" ne "@{$self->{range}}"; } sub set_value { @@ -2529,33 +2599,18 @@ my $class = shift; my $self = $class->SUPER::new ( - state => 0, - connect_activate => \&toggle_flopper, + state => 0, + on_activate => \&toggle_flopper, @_ ); - if ($self->{state}) { - $self->{state} = 0; - $self->toggle_flopper; - } - $self } sub toggle_flopper { my ($self) = @_; - # TODO: use animation - if ($self->{state} = !$self->{state}) { - $CFClient::UI::ROOT->add ($self->{other}); - $self->{other}->move ($self->coord2global (0, $self->{h})); - $self->_emit ("open"); - } else { - $CFClient::UI::ROOT->remove ($self->{other}); - $self->_emit ("close"); - } - - $self->_emit (changed => $self->{state}); + $self->{other}->toggle_visibility; } ############################################################################# @@ -2749,8 +2804,6 @@ $row++; } - -# $range->{range} = [$self->{pos}, 0, $self->{max_pos}, $page]; } sub size_request { @@ -2952,6 +3005,7 @@ my $class = shift; $class->SUPER::new ( + visible => 1, @_, ) } @@ -2988,6 +3042,9 @@ $Y = $child->{req_y} > 0 ? $child->{req_y} : $h - $H - $child->{req_y} + 1 if exists $child->{req_y}; + $X = $self->{user_x} if exists $self->{user_x}; + $Y = $self->{user_y} if exists $self->{user_y}; + $X = List::Util::max 0, List::Util::min $w - $W, int $X + 0.5; $Y = List::Util::max 0, List::Util::min $h - $H, int $Y + 0.5; @@ -3019,8 +3076,8 @@ for (my @widgets = @children; my $w = pop @widgets; ) { push @widgets, $w->children; - $w->{root} = $self; - $w->{visible} = 1; + $w->{root} = $self; + $w->{visible} = $self->{visible} + 1; } for my $child (@children) { @@ -3067,16 +3124,19 @@ } if ($self->{check_size}) { - my @queue = ([], []); + my @queue; for (;;) { if ($self->{check_size}) { - # heuristic: check containers last - push @{ $queue[ ! ! $_->isa ("CFClient::UI::Container") ] }, $_ - for values %{delete $self->{check_size}} + #TODO use array-of-depth approach + + @queue = sort { $a->{visible} <=> $b->{visible} } + @queue, values %{delete $self->{check_size}}; } - my $widget = (pop @{ $queue[0] }) || (pop @{ $queue[1] }) || last; + my $widget = pop @queue || last; + + defined $widget->{visible} or last; # do not resize invisible widgets my ($w, $h) = $widget->{user_w} && $widget->{user_h} ? @$widget{qw(user_w user_h)}