--- deliantra/Deliantra-Client/DC/UI.pm 2006/04/22 12:14:45 1.148 +++ deliantra/Deliantra-Client/DC/UI.pm 2006/04/24 03:33:51 1.160 @@ -10,8 +10,35 @@ our ($FOCUS, $HOVER, $GRAB); # various widgets our $ROOT; +our $TOOLTIP; our $BUTTON_STATE; +sub check_tooltip { + if (!$GRAB) { + for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) { + if (length $widget->{tooltip}) { + + if ($TOOLTIP->{owner} != $widget) { + $TOOLTIP->{owner} = $widget; + + my $tip = $widget->{tooltip}; + + $tip = $tip->($widget) if CODE:: eq ref $tip; + + $TOOLTIP->set_text ($widget->{tooltip}); + $TOOLTIP->move ($widget->coord2global ($widget->{w}, 0)); + $TOOLTIP->show; + } + + return; + } + } + } + + $TOOLTIP->hide; + delete $TOOLTIP->{owner}; +} + # class methods for events sub feed_sdl_key_down_event { $FOCUS->key_down ($_[0]) if $FOCUS; @@ -30,6 +57,8 @@ $GRAB = $widget; $GRAB->update if $GRAB; + + check_tooltip; } $BUTTON_STATE |= 1 << ($ev->{button} - 1); @@ -51,6 +80,8 @@ my $grab = $GRAB; undef $GRAB; $grab->update if $grab; $GRAB->update if $GRAB; + + check_tooltip; } } @@ -65,6 +96,8 @@ $hover->update if $hover && $hover->{can_hover}; $HOVER->update if $HOVER && $HOVER->{can_hover}; + + check_tooltip; } $HOVER->mouse_motion ($ev, $HOVER->coord2local ($x, $y)) if $HOVER; @@ -98,6 +131,7 @@ x => 0, y => 0, z => 0, + can_events => 1, @_ }, $class; @@ -110,6 +144,13 @@ $self } +sub destroy { + my ($self) = @_; + + $self->hide; + %$self = (); +} + sub show { my ($self) = @_; @@ -136,8 +177,13 @@ $self->update; } -sub needs_redraw { - 0 +sub set_size { + my ($self, $w, $h) = @_; + + $self->{user_w} = $w; + $self->{user_h} = $h; + + $self->check_size; } sub size_request { @@ -179,6 +225,13 @@ # nothing to be done } +sub set_max_size { + my ($self, $w, $h) = @_; + + delete $self->{max_w}; $self->{max_w} = $w if $w; + delete $self->{max_h}; $self->{max_h} = $h if $h; +} + # return top left coordinates sub _topleft { my ($self, $x, $y) = @_; @@ -280,6 +333,8 @@ 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}; @@ -296,14 +351,26 @@ sub check_size { my ($self) = @_; - my ($w, $h) = $self->size_request; + $self->{parent} + or return 1; - if ($w != $self->{req_w} || $h != $self->{req_h}) { + 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 - if $self->{parent}; + or $self->size_allocate ( + (List::Util::max $self->{w}, $w), + (List::Util::max $self->{h}, $h), + ); + + 1 + } else { + 0 } } @@ -380,6 +447,11 @@ our @ISA = CFClient::UI::Base::; +sub new { + my ($class, %arg) = @_; + $class->SUPER::new (can_events => 0, %arg); +} + sub size_request { (0, 0) } @@ -397,7 +469,7 @@ my $children = delete $arg{children} || []; - my $self = $class->SUPER::new (children => [], %arg); + my $self = $class->SUPER::new (children => [], can_events => 0, %arg); $self->add ($_) for @$children; $self @@ -426,6 +498,7 @@ $self->{children} = [ grep $_ != $child, @{ $self->{children} } ]; $self->check_size; + $self->update; } sub find_widget { @@ -563,7 +636,7 @@ sub size_request { my ($self) = @_; - @$self{qw(child_w child_h)} = $self->child->size_request; + @$self{qw(child_w child_h)} = @{$self->child}{qw(req_w req_h)}; $self->child->size_allocate (0, 0, @$self{qw(child_w child_h)}); @$self{qw(child_w child_h)} @@ -597,25 +670,6 @@ $self } -sub set_size { - my ($self, $w, $h) = @_; - $self->{req_w} = $w; - $self->{req_h} = $h; - $self->check_size; -} - -sub size_request { - my ($self) = @_; - ($self->{req_w}, $self->{req_h}) -} - -sub size_allocate { - my ($self, $w, $h) = @_; - $self->{w} = $w; - $self->{h} = $h; - $self->child->configure (0, 0, $w, $h); -} - sub _draw { my ($self) = @_; @@ -661,6 +715,7 @@ bg => [1, 1, 1, 1], border_bg => [1, 1, 1, 1], border => 0.8, + can_events => 1, @_ ); @@ -680,8 +735,6 @@ sub size_request { my ($self) = @_; - return ($self->{user_w}, $self->{user_h}) if $self->{user_w} && $self->{user_h}; - my ($w, $h) = $self->SUPER::size_request; ( @@ -839,7 +892,7 @@ for my $x (0 .. $#$row) { my $widget = $row->[$x] or next; - my ($w, $h) = $widget->size_request; + my ($w, $h) = @$widget{qw(req_w req_h)}; $w[$x] = max $w[$x], $w; $h[$y] = max $h[$y], $h; @@ -954,7 +1007,7 @@ my $children = $self->{children}; - my @h = map +($_->size_request)[0], @$children; + my @h = map $_->{req_w}, @$children; my $req_h = List::Util::sum @h; @@ -1012,7 +1065,7 @@ my $children = $self->{children}; - my @h = map +($_->size_request)[1], @$children; + my @h = map $_->{req_h}, @$children; my $req_h = List::Util::sum @h; @@ -1057,12 +1110,14 @@ my $self = $class->SUPER::new ( fg => [1, 1, 1], + #font => default_font fontsize => 1, text => "", align => -1, valign => -1, padding => 2, layout => new CFClient::Layout, + can_events => 0, %arg ); @@ -1094,6 +1149,7 @@ $self->{layout}->set_text ($text); delete $self->{texture}; + $self->check_size; $self->update; } @@ -1103,18 +1159,21 @@ $self->{layout}->set_markup ($markup); delete $self->{texture}; + $self->check_size; $self->update; } sub size_request { my ($self) = @_; - $self->{layout}->set_width; + $self->{layout}->set_font ($self->{font}) if $self->{font}; + $self->{layout}->set_width ($self->{max_w} || -1); $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); my ($w, $h) = $self->{layout}->size; if (exists $self->{template}) { + $self->{template}->set_font ($self->{font}) if $self->{font}; $self->{template}->set_height ($self->{fontsize} * $::FONTSIZE); my ($w2, $h2) = $self->{template}->size; @@ -1139,13 +1198,16 @@ my ($self, $fontsize) = @_; $self->{fontsize} = $fontsize; + delete $self->{texture}; $self->check_size; + $self->update; } sub _draw { my ($self) = @_; my $tex = $self->{texture} ||= do { + $self->{layout}->set_font ($self->{font}) if $self->{font}; $self->{layout}->set_width ($self->{w}); $self->{layout}->set_height (List::Util::min $self->{h}, $self->{fontsize} * $::FONTSIZE); new_from_layout CFClient::Texture $self->{layout} @@ -1195,6 +1257,7 @@ can_hover => 1, can_focus => 1, valign => 0, + can_events => 1, @_ ) } @@ -1232,7 +1295,7 @@ sub size_allocate { my ($self, $w, $h) = @_; - $self->_set_text ($self->{text}); + $self->_set_text (delete $self->{text});#d# don't check for == inside _set_text } sub set_text { @@ -1389,6 +1452,7 @@ can_hover => 1, align => 0, valign => 0, + can_events => 1, @_ ) } @@ -1503,7 +1567,7 @@ sub new { my $class = shift; - my $self = $class->SUPER::new (@_); + my $self = $class->SUPER::new (can_events => 0, @_); $self->{image} or confess "Image has 'image' not set. This is a fatal error!"; @@ -1556,6 +1620,8 @@ our @ISA = CFClient::UI::Base::; +use List::Util qw(min max); + use CFClient::OpenGL; my %tex = ( @@ -1565,7 +1631,7 @@ ], grace => [ map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 } - qw/g1_grace_gauge_empty.png g1_grace_gauge_full.png/ + qw/g1_grace_gauge_empty.png g1_grace_gauge_full.png g1_grace_gauge_overflow.png/ ], hp => [ map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 } @@ -1573,7 +1639,7 @@ ], mana => [ map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 } - qw/g1_mana_gauge_empty.png g1_mana_gauge_full.png/ + qw/g1_mana_gauge_empty.png g1_mana_gauge_full.png g1_mana_gauge_overflow.png/ ], ); @@ -1621,6 +1687,7 @@ my ($self) = @_; my $tex = $tex{$self->{type}}; + my ($t1, $t2, $t3) = @$tex; my ($w, $h) = ($self->{w}, $self->{h}); @@ -1632,35 +1699,45 @@ } my $ycut = $self->{val} / ($self->{max_val} || 1); - $ycut = 1 if $self->{val} > $self->{max_val}; - my $t1 = $tex->[0]; - my $t2 = $tex->[1]; + my $ycut1 = max 0, min 1, $ycut; + my $ycut2 = max 0, min 1, $ycut - 1; + + my $h1 = $self->{h} * (1 - $ycut1); + my $h2 = $self->{h} * (1 - $ycut2); glEnable GL_BLEND; glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; glEnable GL_TEXTURE_2D; glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; - my $h1 = $self->{h} - $ycut * $self->{h}; - my $h2 = $ycut * $self->{h}; - glBindTexture GL_TEXTURE_2D, $t1->{name}; glBegin GL_QUADS; - glTexCoord 0 , 0; glVertex 0 , 0; - glTexCoord 0 , $t1->{t} * (1 - $ycut); glVertex 0 , $h1; - glTexCoord $t1->{s}, $t1->{t} * (1 - $ycut); glVertex $w, $h1; - glTexCoord $t1->{s}, 0; glVertex $w, 0; + glTexCoord 0 , 0; glVertex 0 , 0; + glTexCoord 0 , $t1->{t} * (1 - $ycut1); glVertex 0 , $h1; + glTexCoord $t1->{s}, $t1->{t} * (1 - $ycut1); glVertex $w, $h1; + glTexCoord $t1->{s}, 0; glVertex $w, 0; glEnd; + my $ycut1 = List::Util::min 1, $ycut; glBindTexture GL_TEXTURE_2D, $t2->{name}; glBegin GL_QUADS; - glTexCoord 0 , $t2->{t} * (1 - $ycut); glVertex 0 , $h1; - glTexCoord 0 , $t2->{t}; glVertex 0 , $h1 + $h2; - glTexCoord $t2->{s}, $t2->{t}; glVertex $w, $h1 + $h2; - glTexCoord $t2->{s}, $t2->{t} * (1 - $ycut); glVertex $w, $h1; + glTexCoord 0 , $t2->{t} * (1 - $ycut1); glVertex 0 , $h1; + glTexCoord 0 , $t2->{t} * (1 - $ycut2); glVertex 0 , $h2; + glTexCoord $t2->{s}, $t2->{t} * (1 - $ycut2); glVertex $w, $h2; + glTexCoord $t2->{s}, $t2->{t} * (1 - $ycut1); glVertex $w, $h1; glEnd; + if ($t3) { + glBindTexture GL_TEXTURE_2D, $t3->{name}; + glBegin GL_QUADS; + glTexCoord 0 , $t3->{t} * (1 - $ycut2); glVertex 0 , $h2; + glTexCoord 0 , $t3->{t}; glVertex 0 , $self->{h}; + glTexCoord $t3->{s}, $t3->{t}; glVertex $w, $self->{h}; + glTexCoord $t3->{s}, $t3->{t} * (1 - $ycut2); glVertex $w, $h2; + glEnd; + } + glDisable GL_BLEND; glDisable GL_TEXTURE_2D; } @@ -1672,15 +1749,16 @@ our @ISA = CFClient::UI::VBox::; sub new { - my ($class, %arg) = shift; + my ($class, %arg) = @_; my $self = $class->SUPER::new ( - @_, + tooltip => $arg{type}, + %arg, ); - $self->add ($self->{value} = new CFClient::UI::Label valign => 1, align => 0, template => "999"); - $self->add ($self->{gauge} = new CFClient::UI::VGauge type => $self->{type}, expand => 1); - $self->add ($self->{max} = new CFClient::UI::Label valign => 1, align => 0, template => "999"); + $self->add ($self->{value} = new CFClient::UI::Label valign => +1, align => 0, template => "999", can_events => 1, can_hover => 1); + $self->add ($self->{gauge} = new CFClient::UI::VGauge type => $self->{type}, expand => 1, can_events => 1, can_hover => 1); + $self->add ($self->{max} = new CFClient::UI::Label valign => -1, align => 0, template => "999", can_events => 1, can_hover => 1); $self } @@ -1857,6 +1935,7 @@ my $self = $class->SUPER::new ( fontsize => 1, + #font => default_font @_, layout => (new CFClient::Layout), @@ -1906,6 +1985,7 @@ $self->SUPER::size_allocate ($w, $h); + $self->{layout}->set_font ($self->{font}) if $self->{font}; $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); $self->{layout}->set_width ($self->{children}[0]{w}); @@ -1968,6 +2048,8 @@ my $layout = $self->{layout}; + $layout->set_font ($self->{font}) if $self->{font}; + for my $par (@{$self->{par}}) { my $h = $par->[0]; @@ -2056,6 +2138,7 @@ my $self = $class->SUPER::new ( state => 0, connect_activate => \&toggle_flopper, + can_events => 1, @_ ); @@ -2085,6 +2168,71 @@ ############################################################################# +package CFClient::UI::Tooltip; + +our @ISA = CFClient::UI::Bin::; + +use CFClient::OpenGL; + +sub new { + my $class = shift; + + $class->SUPER::new ( + @_, + can_events => 0, + ) +} + +sub set_text { + my ($self, $text) = @_; + + $self->{label} ||= new CFClient::UI::Label fontsize => 0.8, fg => [0, 0, 0]; + $self->{label}->set_text ($text); + $self->add ($self->{label}); +} + +sub size_request { + my ($self) = @_; + + $self->child->set_max_size ($::WIDTH * 0.3); + + my ($w, $h) = @{$self->child}{qw(req_w req_h)}; + + ($w + 4, $h + 4) +} + +sub _draw { + my ($self) = @_; + + glPushMatrix; + glTranslate 0.375, 0.375; + + my ($w, $h) = @$self{qw(w h)}; + + glColor 1, 0.8, 0.4; + glBegin GL_QUADS; + glVertex 0 , 0; + glVertex 0 , $h; + glVertex $w, $h; + glVertex $w, 0; + glEnd; + + glColor 0, 0, 0; + glBegin GL_LINE_LOOP; + glVertex 0 , 0; + glVertex 0 , $h; + glVertex $w, $h; + glVertex $w, 0; + glEnd; + + glPopMatrix; + + glTranslate 2, 2; + $self->SUPER::_draw; +} + +############################################################################# + package CFClient::UI::Root; our @ISA = CFClient::UI::Container::; @@ -2094,7 +2242,7 @@ sub check_size { my ($self) = @_; - $self->configure (0, 0, $::WITH, $::HEIGHT); + $self->configure (0, 0, $::WIDTH, $::HEIGHT); } sub size_request { @@ -2106,8 +2254,13 @@ $self->SUPER::configure ($x, $y, $w, $h); - $_->configure ($_->{x}, $_->{y}, $_->size_request) - for @{$self->{children}}; + for my $child (@{$self->{children}}) { + my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)}; + + $X = List::Util::max 0, List::Util::min $w - $W, $X; + $Y = List::Util::max 0, List::Util::min $h - $H, $Y; + $child->configure ($X, $Y, $W,$H); + } } sub _topleft { @@ -2164,6 +2317,7 @@ package CFClient::UI; $ROOT = new CFClient::UI::Root; +$TOOLTIP = new CFClient::UI::Tooltip; 1