--- deliantra/Deliantra-Client/DC/UI.pm 2007/08/21 02:41:52 1.431 +++ deliantra/Deliantra-Client/DC/UI.pm 2007/12/16 00:21:58 1.446 @@ -4,7 +4,6 @@ use strict; use List::Util (); -use Event; use CFPlus; use CFPlus::Pod; @@ -19,7 +18,9 @@ our %WIDGET; # all widgets, weak-referenced -our $TOOLTIP_WATCHER = Event->idle (min => 1/60, cb => sub { +our $TOOLTIP_WATCHER = EV::timer_ns 0, 1/60, sub { + $_[0]->stop; + if (!$GRAB) { for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) { if (length $widget->{tooltip}) { @@ -32,10 +33,6 @@ return if $ENV{CFPLUS_DEBUG} & 8; - my $tip = $widget->{tooltip}; - - $tip = $tip->($widget) if CODE:: eq ref $tip; - $TOOLTIP->set_tooltip_from ($widget); $TOOLTIP->show; } @@ -48,7 +45,7 @@ $TOOLTIP->hide; $TOOLTIP->{owner}->emit ("tooltip_hide") if $TOOLTIP->{owner}; delete $TOOLTIP->{owner}; -}); +}; sub get_layout { my $layout; @@ -93,7 +90,7 @@ $hover->update if $hover && $hover->{can_hover}; $HOVER->update if $HOVER && $HOVER->{can_hover}; - $TOOLTIP_WATCHER->start; + $TOOLTIP_WATCHER->again; } } @@ -109,7 +106,7 @@ $GRAB = $widget; $GRAB->update if $GRAB; - $TOOLTIP_WATCHER->cb->(); + $TOOLTIP_WATCHER->invoke; } if ($GRAB) { @@ -144,7 +141,7 @@ $GRAB->update if $GRAB; check_hover $widget; - $TOOLTIP_WATCHER->cb->(); + $TOOLTIP_WATCHER->invoke; } } @@ -275,7 +272,7 @@ } sub TO_JSON { - { __w_ => $_[0]{s_id} } + { "\fw" => $_[0]{s_id} } } sub show { @@ -314,7 +311,7 @@ undef $GRAB if $GRAB == $self; undef $HOVER if $HOVER == $self; - $CFPlus::UI::TOOLTIP_WATCHER->cb->() + $CFPlus::UI::TOOLTIP_WATCHER->invoke if $TOOLTIP->{owner} == $self; $self->emit ("focus_out"); @@ -366,6 +363,16 @@ $self->realloc; } +# traverse the widget chain up to find the maximum "physical" size constraints +sub get_max_wh { + my ($self) = @_; + + return $self->{parent}->get_max_wh + if $self->{parent}; + + ($::WIDTH, $::HEIGHT) +} + sub size_request { require Carp; Carp::confess "size_request is abstract"; @@ -435,7 +442,7 @@ if ($CFPlus::UI::TOOLTIP->{owner} == $self) { delete $CFPlus::UI::TOOLTIP->{owner}; - $CFPlus::UI::TOOLTIP_WATCHER->cb->(); + $CFPlus::UI::TOOLTIP_WATCHER->invoke; } } @@ -443,7 +450,7 @@ sub coord2local { my ($self, $x, $y) = @_; - Carp::confess unless $self->{parent};#d# + return (undef, undef) unless $self->{parent}; $self->{parent}->coord2local ($x - $self->{x}, $y - $self->{y}) } @@ -452,7 +459,7 @@ sub coord2global { my ($self, $x, $y) = @_; - Carp::confess unless $self->{parent};#d# + return (undef, undef) unless $self->{parent}; $self->{parent}->coord2global ($x + $self->{x}, $y + $self->{y}) } @@ -823,7 +830,6 @@ } ############################################################################# - # back-buffered drawing area package CFPlus::UI::Window; @@ -1384,6 +1390,15 @@ int $_[0]{border} * $::FONTSIZE } +sub get_max_wh { + my ($self) = @_; + + return ($self->{w}, $self->{h}) + if $self->{visible} && $self->{w}; + + $self->SUPER::get_max_wh +} + sub size_request { my ($self) = @_; @@ -1948,8 +1963,10 @@ my ($self) = @_; $self->{size_req} ||= do { + my ($max_w, $max_h) = $self->get_max_wh; + $self->{layout}->set_font ($self->{font}) if $self->{font}; - $self->{layout}->set_width ($self->{max_w} || -1); + $self->{layout}->set_width ($self->{max_w} || $max_w || -1); $self->{layout}->set_ellipsise ($self->{ellipsise}); $self->{layout}->set_single_paragraph_mode ($self->{ellipsise}); $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); @@ -2239,23 +2256,22 @@ glColor_premultiply @{$self->{active_fg}}; glBegin GL_LINES; - glVertex 0.5 + $self->{cur_x} + $self->{ox}, $self->{cur_y} + $self->{oy}; - glVertex 0.5 + $self->{cur_x} + $self->{ox}, $self->{cur_y} + $self->{oy} + $self->{cur_h}; + glVertex $self->{cur_x} + $self->{ox} + .5, $self->{cur_y} + $self->{oy}; + glVertex $self->{cur_x} + $self->{ox} + .5, $self->{cur_y} + $self->{oy} + $self->{cur_h}; glEnd; glLineWidth 3; glColor @{$self->{active_outline}}; - glRect_lineloop 0, 0, $self->{w} - 1, $self->{h} - 1; + glRect_lineloop 1.5, 1.5, $self->{w} - 1.5, $self->{h} - 1.5; glLineWidth 1; } else { glColor @{$self->{outline}}; - glTranslate .375, .375; glBegin GL_LINE_STRIP; - glVertex 0, $self->{h} * .5; - glVertex 0, $self->{h} - 3; - glVertex $self->{w} - 1, $self->{h} - 3; - glVertex $self->{w} - 1, $self->{h} * .5; + glVertex .5, $self->{h} * .5; + glVertex .5, $self->{h} - 2.5; + glVertex $self->{w} - .5, $self->{h} - 2.5; + glVertex $self->{w} - .5, $self->{h} * .5; glEnd; } } @@ -2514,7 +2530,7 @@ $self->SUPER::_draw; - glTranslate $self->{padding_x} + 0.375, $self->{padding_y} + 0.375, 0; + glTranslate $self->{padding_x}, $self->{padding_y}, 0; my ($w, $h) = @$self{qw(w h)}; @@ -2802,6 +2818,7 @@ align => 0, can_events => 1, ellipsise => 1, + label => "%d%%", %arg, ); @@ -2810,17 +2827,27 @@ $self } +sub set_label { + my ($self, $label) = @_; + + return if $self->{label} eq $label; + $self->{label} = $label; + + $self->CFPlus::UI::Progress::set_value (0 + delete $self->{value}); +} + sub set_value { my ($self, $value) = @_; - if ($self->{value} != $value) { + if ($self->{value} ne $value) { $self->{value} = $value; if ($value < 0) { $self->set_text ("-"); } else { - $self->set_text (sprintf "%d%%", $value * 100); + $self->set_text (sprintf $self->{label}, $value * 100); } + $self->update; } } @@ -2832,16 +2859,16 @@ glBlendFunc GL_ONE, GL_ONE_MINUS_SRC_ALPHA; if ($self->{value} >= 0) { - my $s = 3 + ($self->{w} - 6) * $self->{value}; + my $s = int 2 + ($self->{w} - 4) * $self->{value}; glColor_premultiply @{$self->{bar}}; - glRect 2, 2, $s, $self->{h} - 2; + glRect 2, 2, $s, $self->{h} - 2; glColor_premultiply @{$self->{bg}}; - glRect $s + 1, 0, $self->{w} - 2, $self->{h} - 2; + glRect $s, 2, $self->{w} - 2, $self->{h} - 2; } glColor_premultiply @{$self->{outline}}; - glRect_lineloop 1, 1, $self->{w} - 2, $self->{h} - 2; + glRect_lineloop 1.5, 1.5, $self->{w} - 1.5, $self->{h} - 1.5; glDisable GL_BLEND; @@ -2861,6 +2888,15 @@ my ($class, %arg) = @_; my $self = $class->SUPER::new ( + tooltip => sub { + my ($self) = @_; + + sprintf "level %d\n%s points\n%s next level\n%s to go", + $self->{lvl}, + ::formsep ($self->{exp}), + ::formsep ($self->{nxt}), + ::formsep ($self->{nxt} - $self->{exp}), + }, %arg ); @@ -2882,12 +2918,17 @@ sub set_value { my ($self, $lvl, $exp) = @_; + $self->{lvl} = $lvl; + $self->{exp} = $exp; + my $v = -1; if ($::CONN && (my $table = $::CONN->{exp_table})) { my $l0 = $table->[$lvl - 1]; my $l1 = $table->[$lvl]; + $self->{nxt} = $l1; + $v = ($exp - $l0) / ($l1 - $l0); } @@ -3534,23 +3575,24 @@ sub set_tooltip_from { my ($self, $widget) = @_; - $widget->{tooltip} = CFPlus::Pod::section_label tooltip => $1 - if $widget->{tooltip} =~ /^#(.*)$/; - - my $tooltip = $widget->{tooltip}; + my $tip = $widget->{tooltip}; + $tip = $tip->($widget) if "CODE" eq ref $tip; + + $tip = CFPlus::Pod::section_label tooltip => $1 + if $tip =~ /^#(.*)$/; if ($ENV{CFPLUS_DEBUG} & 2) { - $tooltip .= "\n\n" . (ref $widget) . "\n" - . "$widget->{x} $widget->{y} $widget->{w} $widget->{h}\n" - . "req $widget->{req_w} $widget->{req_h}\n" - . "visible $widget->{visible}"; + $tip .= "\n\n" . (ref $widget) . "\n" + . "$widget->{x} $widget->{y} $widget->{w} $widget->{h}\n" + . "req $widget->{req_w} $widget->{req_h}\n" + . "visible $widget->{visible}"; } - $tooltip =~ s/^\n+//; - $tooltip =~ s/\n+$//; + $tip =~ s/^\n+//; + $tip =~ s/\n+$//; $self->add (new CFPlus::UI::Label - markup => $tooltip, + markup => $tip, max_w => ($widget->{tooltip_width} || 0.25) * $::WIDTH, fontsize => 0.8, style => 1, # FLAG_INVERSE @@ -3598,17 +3640,15 @@ sub _draw { my ($self) = @_; - glTranslate 0.375, 0.375; - my ($w, $h) = @$self{qw(w h)}; glColor 1, 0.8, 0.4; glRect 0, 0, $w, $h; glColor 0, 0, 0; - glRect_lineloop 0, 0, $w, $h; + glRect_lineloop .5, .5, $w + .5, $h + .5; - glTranslate 2 - 0.375, 2 - 0.375; + glTranslate 2, 2; $self->SUPER::_draw; } @@ -3636,23 +3676,20 @@ CFPlus::weaken (my $widget = $self); $widget->{animspeed} = List::Util::max 0.05, $widget->{animspeed}; - $widget->{anim_start} = $self->{animspeed} * int Event::time / $self->{animspeed}; - $self->{timer} = Event->timer ( - parked => 1, - cb => sub { - return unless $::CONN; - - my $w = $widget - or return; - - ++$w->{frame}; - $w->update_face; - - # somehow, $widget can go away - $w->update; - $w->update_timer; - }, - ); + $widget->{anim_start} = $self->{animspeed} * int EV::now / $self->{animspeed}; + $self->{timer} = EV::timer_ns 0, 0, sub { + return unless $::CONN; + + my $w = $widget + or return; + + ++$w->{frame}; + $w->update_face; + + # somehow, $widget can go away + $w->update; + $w->update_timer; + }; $self->update_face; $self->update_timer; @@ -3667,10 +3704,10 @@ return unless $self->{timer}; if ($self->{visible}) { - $self->{timer}->at ( + $self->{timer}->set ( $self->{anim_start} + $self->{animspeed} - * int 1.5 + (Event::time - $self->{anim_start}) / $self->{animspeed} + * int 1.5 + (EV::now - $self->{anim_start}) / $self->{animspeed} ); $self->{timer}->start; } else { @@ -3935,14 +3972,17 @@ package CFPlus::UI::Notebook; +use CFPlus::OpenGL; + our @ISA = CFPlus::UI::VBox::; sub new { my $class = shift; my $self = $class->SUPER::new ( - buttonbar => (new CFPlus::UI::Buttonbar), - multiplexer => (new CFPlus::UI::Multiplexer expand => 1), + buttonbar => (new CFPlus::UI::Buttonbar), + multiplexer => (new CFPlus::UI::Multiplexer expand => 1), + active_outline => [.7, .7, 0.2], # filter => # will be put between multiplexer and $self @_, ); @@ -4026,6 +4066,26 @@ $self->emit (page_changed => $self->{multiplexer}{current}); } +sub _draw { + my ($self) = @_; + + $self->SUPER::_draw (); + + if (my $cur = $self->{multiplexer}{current}) { + if ($cur = $cur->{c_tab_}) { + glTranslate $self->{buttonbar}{x} + $cur->{x}, + $self->{buttonbar}{y} + $cur->{y}; + glLineWidth 3; + #glEnable GL_BLEND; + #glBlendFunc GL_ONE, GL_ONE_MINUS_SRC_ALPHA; + glColor @{$self->{active_outline}}; + glRect_lineloop 1.5, 1.5, $cur->{w} - 1.5, $cur->{h} - 1.5; + glLineWidth 1; + #glDisable GL_BLEND; + } + } +} + ############################################################################# package CFPlus::UI::Selector; @@ -4065,12 +4125,13 @@ sub _set_value { my ($self, $value) = @_; - my ($item) = grep $_->[0] eq $value, @{ $self->{options} } + my ($item) = grep $_->[0] eq $value, @{ $self->{options} }; + $item ||= $self->{options}[0] or return; $self->{value} = $item->[0]; $self->set_markup ("$item->[1] ⇓"); - $self->set_tooltip ($item->[2]); +# $self->set_tooltip ($item->[2]); } sub set_value { @@ -4082,6 +4143,13 @@ $self->emit (changed => $value); } +sub set_options { + my ($self, $options) = @_; + + $self->{options} = $options; + $self->_set_value ($self->{value}); +} + ############################################################################# package CFPlus::UI::Statusbox; @@ -4098,7 +4166,7 @@ CFPlus::weaken (my $this = $self); - $self->{timer} = Event->timer (after => 1, interval => 1, cb => sub { $this->reorder }); + $self->{timer} = EV::timer 1, 1, sub { $this->reorder }; $self } @@ -4116,6 +4184,8 @@ delete $self->{item}{$k} if $v->{timeout} < $NOW; } + $self->{timer}->set (1, 1); + my @widgets; my @items = sort { @@ -4123,8 +4193,6 @@ or $b->{id} <=> $a->{id} } values %{ $self->{item} }; - $self->{timer}->interval (1); - my $count = 10 + 1; for my $item (@items) { last unless --$count; @@ -4157,7 +4225,7 @@ $label->update; $label->set_max_size (undef, $label->{req_h} * $diff) if $diff < 1; - $self->{timer}->interval (1/30); + $self->{timer}->set (1/30, 1/30); } else { $label->{fg}[3] = $item->{fg}[3] || 1; }