--- deliantra/Deliantra-Client/DC/UI.pm 2007/07/20 16:32:17 1.385 +++ deliantra/Deliantra-Client/DC/UI.pm 2007/07/21 21:25:23 1.403 @@ -115,8 +115,12 @@ if ($GRAB) { if ($ev->{button} == 4 || $ev->{button} == 5) { # mousewheel - $ev->{dx} = 0; - $ev->{dy} = $ev->{button} * 2 - 9; + my $delta = $ev->{button} * 2 - 9; + my $shift = $ev->{mod} & CFPlus::KMOD_SHIFT; + + $ev->{dx} = $shift ? $delta : 0; + $ev->{dy} = $shift ? 0 : $delta; + $GRAB->emit (mouse_wheel => $ev); } else { $GRAB->emit (button_down => $ev) @@ -549,17 +553,8 @@ $self->{parent} && $self->{parent}->emit ($signal, @args) } -sub find_widget { - my ($self, $x, $y) = @_; - - return () unless $self->{can_events}; - - return $self - if $x >= $self->{x} && $x < $self->{x} + $self->{w} - && $y >= $self->{y} && $y < $self->{y} + $self->{h}; - - () -} +#sub find_widget { +# in .xs sub set_parent { my ($self, $parent) = @_; @@ -653,7 +648,6 @@ warn "no draw defined for $self\n"; } -my $cntx;#d# sub DESTROY { my ($self) = @_; @@ -748,7 +742,7 @@ ); $self->add (@$children) - if $children; + if $children && @$children; $self } @@ -767,6 +761,7 @@ $_->set_parent ($self) for @widgets; + # TODO: only do this in widgets that need it, e.g. root, fixed use sort 'stable'; $self->{children} = [ @@ -775,6 +770,8 @@ ]; $self->realloc; + + map $_+0, @widgets } sub children { @@ -795,7 +792,7 @@ sub clear { my ($self) = @_; - my $children = delete $self->{children}; + my $children = $self->{children}; $self->{children} = []; for (@$children) { @@ -965,8 +962,8 @@ my ($w, $h) = @{$self->child}{qw(req_w req_h)}; - $w = 10 if $self->{scroll_x}; - $h = 10 if $self->{scroll_y}; + $w = 1 if $self->{scroll_x}; + $h = 1 if $self->{scroll_y}; ($w, $h) } @@ -1022,7 +1019,7 @@ if ( $x >= $self->{x} && $x < $self->{x} + $self->{w} && $y >= $self->{y} && $y < $self->{y} + $self->{h} ) { - $self->child->find_widget ($x + $self->{view_x}, $y + $self->{view_y}) + $self->child->find_widget ($x + $self->{view_x}, $y + $self->{view_y}) } else { $self->CFPlus::UI::Base::find_widget ($x, $y) } @@ -1053,6 +1050,8 @@ my $self; my $hslider = new CFPlus::UI::Slider + col => 0, + row => 1, vertical => 0, range => [0, 0, 1, 0.01], # HACK fix on_changed => sub { @@ -1062,6 +1061,8 @@ ; my $vslider = new CFPlus::UI::Slider + col => 1, + row => 0, vertical => 1, range => [0, 0, 1, 0.01], # HACK fix on_changed => sub { @@ -1082,6 +1083,8 @@ ); $self->{vp} = new CFPlus::UI::ViewPort + col => 0, + row => 0, expand => 1, scroll_x => $self->{scroll_x}, scroll_y => $self->{scroll_y}, @@ -1093,17 +1096,20 @@ 0 }, + on_size_allocate => sub { + my ($vp, $w, $h) = @_; + $vp->{parent}->update_slider; + 0 + }, ; - $self->SUPER::add_at (0, 0, $self->{vp}); + $self->SUPER::add ($self->{vp}); $self->add ($child) if $child; $self } -#TODO# update range on size_allocate depending on child - sub add { my ($self, $widget) = @_; @@ -1115,38 +1121,54 @@ my $child = ($self->{vp} or return)->child; - my ($w1, $w2) = ($child->{w}, $self->{vp}{w}); - $self->{hslider}->set_range ([$self->{hslider}{range}[0], 0, $w1, $w2, 1]); + if ($self->{scroll_x}) { + my ($w1, $w2) = ($child->{req_w}, $self->{vp}{w}); + $self->{hslider}->set_range ([$self->{hslider}{range}[0], 0, $w1, $w2, 1]); + + my $visible = $w1 > $w2; + if ($visible != $self->{hslider_visible}) { + $self->{hslider_visible} = $visible; + $visible ? $self->SUPER::add ($self->{hslider}) + : $self->SUPER::remove ($self->{hslider}); + } + } - my $visible = $w1 > $w2; - if ($visible != $self->{hslider}{visible}) { - $visible ? $self->SUPER::add_at (0, 1, $self->{hslider}) - : $self->{hslider}->hide; - } - - my ($h1, $h2) = ($child->{h}, $self->{vp}{h}); - $self->{vslider}->set_range ([$self->{vslider}{range}[0], 0, $h1, $h2, 1]); - - my $visible = $h1 > $h2; - if ($visible != $self->{vslider}{visible}) { - $visible ? $self->SUPER::add_at (1, 0, $self->{vslider}) - : $self->{vslider}->hide; + if ($self->{scroll_y}) { + my ($h1, $h2) = ($child->{req_h}, $self->{vp}{h}); + $self->{vslider}->set_range ([$self->{vslider}{range}[0], 0, $h1, $h2, 1]); + + my $visible = $h1 > $h2; + if ($visible != $self->{vslider_visible}) { + $self->{vslider_visible} = $visible; + $visible ? $self->SUPER::add ($self->{vslider}) + : $self->SUPER::remove ($self->{vslider}); + } } } -sub update { - my ($self) = @_; +sub start_dragging { + my ($self, $ev) = @_; - $self->SUPER::update; - $self->update_slider; + $self->grab_focus; + + my $ox = $self->{vp}{view_x}; + my $oy = $self->{vp}{view_y}; + + $self->{motion} = sub { + my ($ev, $x, $y) = @_; + + $ox -= $ev->{xrel}; + $oy -= $ev->{yrel}; + + $self->{vp}->set_offset ($ox, $oy); + }; } sub invoke_mouse_wheel { my ($self, $ev) = @_; - return 0 unless $ev->{dy}; # only vertical movements for now - - $self->{vslider}->emit (mouse_wheel => $ev); + $self->{vslider}->emit (mouse_wheel => $ev) if $self->{vslider_visible}; + $self->{hslider}->emit (mouse_wheel => $ev) if $self->{hslider_visible}; 1 } @@ -1155,18 +1177,7 @@ 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; - }; - + $self->start_dragging ($ev); return 1; } @@ -1586,7 +1597,7 @@ package CFPlus::UI::Table; -our @ISA = CFPlus::UI::Base::; +our @ISA = CFPlus::UI::Container::; use List::Util qw(max sum); @@ -1596,81 +1607,66 @@ my $class = shift; $class->SUPER::new ( - children => [], col_expand => [], row_expand => [], @_, ) } -sub children { - grep $_, map @$_, grep $_, @{ $_[0]{children} } -} - -# TODO: store row/col info in child widget and use standard add/del sub add { - my $self = shift; + my ($self, @widgets) = @_; + + for my $child (@widgets) { + $child->{rowspan} ||= 1; + $child->{colspan} ||= 1; + } - Carp::cluck "please use the add_at method instead of calling add, thank you.\n";#d# - $self->add_at (@_); + $self->SUPER::add (@widgets); } sub add_at { my $self = shift; + my @widgets; + while (@_) { my ($col, $row, $child) = splice @_, 0, 3, (); - $child->set_parent ($self); - $self->{children}[$row][$col] = $child; - } - - $self->{force_realloc} = 1; - $self->{force_size_alloc} = 1; - $self->realloc; -} - -sub remove { - my ($self, $child) = @_; + $child->{row} = $row; + $child->{col} = $col; - for (@{ $self->{children} }) { - for (@{ $_ || [] }) { - $_ = undef if $_ == $child; - } + push @widgets, $child; } + + $self->add (@widgets); } -# TODO: move to container class maybe? send children a signal on removal? -sub clear { +sub get_wh { my ($self) = @_; + my (@w, @h); + my @children = $self->children; - delete $self->{children}; - - for (@children) { - delete $_->{parent}; - $_->hide; - } - $self->realloc; -} + # first pass, columns + for my $widget (sort { $a->{colspan} <=> $b->{colspan} } @children) { + my ($c, $w, $cs) = @$widget{qw(col req_w colspan)}; -sub get_wh { - my ($self) = @_; + my $sw = sum @w[$c .. $c + $cs - 1]; - my (@w, @h); + if ($w > $sw) { + $_ += ($w - $sw) / ($sw ? $sw / $_ : $cs) for @w[$c .. $c + $cs - 1]; + } + } - for my $y (0 .. $#{$self->{children}}) { - my $row = $self->{children}[$y] - or next; - - for my $x (0 .. $#$row) { - my $widget = $row->[$x] - or next; - my ($w, $h) = @$widget{qw(req_w req_h)}; + # second pass, rows + for my $widget (sort { $a->{rowspan} <=> $b->{rowspan} } @children) { + my ($r, $h, $rs) = @$widget{qw(row req_h rowspan)}; - $w[$x] = max $w[$x], $w; - $h[$y] = max $h[$y], $h; + my $sh = sum @h[$r .. $r + $rs - 1]; + + if ($h > $sh) { + $_ += ($h - $sh) / ($sh ? $sh / $_ : $rs) for @h[$r .. $r + $rs - 1]; } } @@ -1696,7 +1692,7 @@ my $req_w = (sum @$ws) || 1; my $req_h = (sum @$hs) || 1; - # TODO: nicer code + # now linearly scale the rows/columns to the allocated size my @col_expand = @{$self->{col_expand}}; @col_expand = (1) x @$ws unless @col_expand; my $col_expand = (sum @col_expand) || 1; @@ -1713,55 +1709,21 @@ CFPlus::UI::harmonize $hs; - my $y; - - for my $r (0 .. $#{$self->{children}}) { - my $row = $self->{children}[$r] - or next; - - my $x = 0; - my $row_h = $hs->[$r]; - - for my $c (0 .. $#$row) { - my $col_w = $ws->[$c]; + my @x; for (0 .. $#$ws) { $x[$_ + 1] = $x[$_] + $ws->[$_] } + my @y; for (0 .. $#$hs) { $y[$_ + 1] = $y[$_] + $hs->[$_] } - if (my $widget = $row->[$c]) { - $widget->configure ($x, $y, $col_w, $row_h); - } - - $x += $col_w; - } + for my $widget ($self->children) { + my ($r, $c, $w, $h, $rs, $cs) = @$widget{qw(row col req_w req_h rowspan colspan)}; - $y += $row_h; + $widget->configure ( + $x[$c], $y[$r], + $x[$c + $cs] - $x[$c], $y[$r + $rs] - $y[$r], + ); } 1 } -sub find_widget { - my ($self, $x, $y) = @_; - - $x -= $self->{x}; - $y -= $self->{y}; - - my $res; - - for (grep $_, map @$_, grep $_, @{ $self->{children} }) { - $res = $_->find_widget ($x, $y) - and return $res; - } - - $self->SUPER::find_widget ($x + $self->{x}, $y + $self->{y}) -} - -sub _draw { - my ($self) = @_; - - for (grep $_, @{$self->{children}}) { - $_->draw for grep $_, @$_; - } -} - ############################################################################# package CFPlus::UI::Fixed; @@ -1770,7 +1732,7 @@ our @ISA = CFPlus::UI::Container::; -sub add { +sub add_fixed { my ($self, $child, $posmode, $x, $y, $sizemode, $w, $h) = @_; $child->{_fixed} = [$posmode, $x, $y, $sizemode, $w, $h]; @@ -1835,8 +1797,8 @@ $x = _scale $pos, $x, $W; $y = _scale $pos, $x, $H; - $w = _scale $size, $w, $child->{req_w}; - $h = _scale $size, $h, $child->{req_h}; + $w = _scale $size, $w, $W; + $h = _scale $size, $h, $H; $child->configure ($x, $y, $w, $h); } @@ -3570,6 +3532,7 @@ if ($anim && @$anim) { delete $self->{wait_face}; $self->{face} = $anim->[ $self->{frame} % @$anim ]; + $self->{tex} = $::CONN->{texture}[ $::CONN->{faceid}[$self->{face}] ]; } } } @@ -3580,6 +3543,7 @@ if ($::CONN) { if (my $faceid = $::CONN->{faceid}[$self->{face}]) { if (my $tex = $::CONN->{texture}[$faceid]) { + $self->{tex} = $tex; return ($self->{size_w} || $tex->{w}, $self->{size_h} || $tex->{h}); } else { $self->{wait_face} ||= $::CONN->connect_face_update ($faceid, sub { @@ -3611,16 +3575,9 @@ sub _draw { my ($self) = @_; - return unless $::CONN; - $self->SUPER::_draw; - my $faceid = $::CONN->{faceid}[$self->{face}] - or return; - - my $tex = $::CONN->{texture}[$faceid]; - - if ($tex) { + if (my $tex = $self->{tex}) { glEnable GL_TEXTURE_2D; glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; glColor 0, 0, 0, 1; @@ -4186,7 +4143,7 @@ for values %{delete $self->{refresh_hook}}; } - if ($self->{realloc}) { + while ($self->{realloc}) { my %queue; my @queue; my $widget; @@ -4243,40 +4200,37 @@ delete $self->{realloc}{$widget+0}; } - } - - while (my $size_alloc = delete $self->{size_alloc}) { - my @queue = sort { $b->{visible} <=> $a->{visible} } - values %$size_alloc; - while () { - my $widget = pop @queue || last; + while (my $size_alloc = delete $self->{size_alloc}) { + my @queue = sort { $a->{visible} <=> $b->{visible} } + values %$size_alloc; - my ($w, $h) = @$widget{qw(alloc_w alloc_h)}; + while () { + my $widget = pop @queue || last; - $w = 0 if $w < 0; - $h = 0 if $h < 0; + my ($w, $h) = @$widget{qw(alloc_w alloc_h)}; - $w = max $widget->{min_w}, $w; - $h = max $widget->{min_h}, $h; + $w = max $widget->{min_w}, $w; + $h = max $widget->{min_h}, $h; # $w = min $self->{w} - $widget->{x}, $w if $self->{w}; # $h = min $self->{h} - $widget->{y}, $h if $self->{h}; - $w = min $widget->{max_w}, $w if exists $widget->{max_w}; - $h = min $widget->{max_h}, $h if exists $widget->{max_h}; + $w = min $widget->{max_w}, $w if exists $widget->{max_w}; + $h = min $widget->{max_h}, $h if exists $widget->{max_h}; - $w = int $w + 0.5; - $h = int $h + 0.5; + $w = int $w + 0.5; + $h = int $h + 0.5; - if ($widget->{w} != $w || $widget->{h} != $h || delete $widget->{force_size_alloc}) { - $widget->{old_w} = $widget->{w}; - $widget->{old_h} = $widget->{h}; + if ($widget->{w} != $w || $widget->{h} != $h || delete $widget->{force_size_alloc}) { + $widget->{old_w} = $widget->{w}; + $widget->{old_h} = $widget->{h}; - $widget->{w} = $w; - $widget->{h} = $h; + $widget->{w} = $w; + $widget->{h} = $h; - $widget->emit (size_allocate => $w, $h); + $widget->emit (size_allocate => $w, $h); + } } } }