--- deliantra/Deliantra-Client/DC/UI.pm 2006/05/09 22:49:32 1.192 +++ deliantra/Deliantra-Client/DC/UI.pm 2006/05/11 23:54:31 1.195 @@ -1,5 +1,6 @@ package CFClient::UI; +use utf8; use strict; use Scalar::Util (); @@ -25,7 +26,7 @@ $tip = $tip->($widget) if CODE:: eq ref $tip; - $TOOLTIP->set_markup ($widget->{tooltip}); + $TOOLTIP->set_markup ($widget->{tooltip}, $widget->{tooltip_font}); $TOOLTIP->show; @@ -382,8 +383,10 @@ sub set_parent { my ($self, $parent) = @_; - $self->{_tree_depth} = $parent->{_tree_depth} + 1; Scalar::Util::weaken ($self->{parent} = $parent); + + $self->check_size + unless exists $self->{req_w}; } sub check_size { @@ -508,9 +511,7 @@ @{$self->{children}}, @widgets ]; - $_->check_size - for @widgets; - + $self->check_size; $self->update; } @@ -668,15 +669,12 @@ my $tex = $self->{texture} or return; - glEnable GL_BLEND; - glBlendFunc GL_ONE, GL_ONE_MINUS_SRC_ALPHA; glEnable GL_TEXTURE_2D; glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; glColor 0, 0, 0, 1; - $tex->draw_quad (0, 0, $w, $h); + $tex->draw_quad_alpha_premultiplied (0, 0, $w, $h); - glDisable GL_BLEND; glDisable GL_TEXTURE_2D; } @@ -1215,6 +1213,8 @@ sub size_allocate { my ($self, $w, $h) = @_; + Carp::confess "negative size" if $w < 0 || $h < 0;#d# + my $children = $self->{children}; my @h = map $_->{req_h}, @$children; @@ -1263,12 +1263,13 @@ my $self = $class->SUPER::new ( fg => [1, 1, 1], #font => default_font + #text => initial text + #markup => initial narkup + layout => (new CFClient::Layout), fontsize => 1, - text => "", align => -1, valign => -1, padding => 2, - layout => new CFClient::Layout, can_events => 0, %arg ); @@ -1279,8 +1280,11 @@ $self->{template} = $layout; } - $self->set_text (delete $self->{text}) if exists $self->{text}; - $self->set_markup (delete $self->{markup}) if exists $self->{markup}; + if (exists $self->{markup}) { + $self->set_markup (delete $self->{markup}); + } else { + $self->set_text (delete $self->{text}); + } $self } @@ -1308,6 +1312,7 @@ return if $self->{text} eq "T$text"; $self->{text} = "T$text"; + $self->{layout} = new CFClient::Layout if $self->{layout}->is_rgba; $self->{layout}->set_text ($text); $self->update; @@ -1320,6 +1325,9 @@ return if $self->{text} eq "M$markup"; $self->{text} = "M$markup"; + my $rgba = $markup =~ /span.*(?:foreground|background)/; + + $self->{layout} = new CFClient::Layout $rgba if $self->{layout}->is_rgba != $rgba; $self->{layout}->set_markup ($markup); $self->update; @@ -1371,35 +1379,35 @@ my ($self) = @_; my $tex = $self->{texture} ||= do { + $self->{layout}->set_foreground (@{$self->{fg}}); $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} - }; - 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 $tex = new_from_layout CFClient::Texture $self->{layout}; - glColor @{$self->{fg}}; + $self->{ox} = int $self->{align} < 0 ? $self->{padding} + : $self->{align} > 0 ? $self->{w} - $tex->{w} - $self->{padding} + : ($self->{w} - $tex->{w}) * 0.5; - $self->{ox} = int ( - $self->{align} < 0 ? $self->{padding} - : $self->{align} > 0 ? $self->{w} - $tex->{w} - $self->{padding} - : ($self->{w} - $tex->{w}) * 0.5 - ); + $self->{oy} = int $self->{valign} < 0 ? $self->{padding} + : $self->{valign} > 0 ? $self->{h} - $tex->{h} - $self->{padding} + : ($self->{h} - $tex->{h}) * 0.5; - $self->{oy} = int ( - $self->{valign} < 0 ? $self->{padding} - : $self->{valign} > 0 ? $self->{h} - $tex->{h} - $self->{padding} - : ($self->{h} - $tex->{h}) * 0.5 - ); + $tex + }; - $tex->draw_quad ($self->{ox}, $self->{oy}); + glEnable GL_TEXTURE_2D; + glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; + + if ($tex->{format} == GL_ALPHA) { + glColor @{$self->{fg}}; + $tex->draw_quad_alpha ($self->{ox}, $self->{oy}); + } else { + $tex->draw_quad_alpha_premultiplied ($self->{ox}, $self->{oy}); + } glDisable GL_TEXTURE_2D; - glDisable GL_BLEND; } ############################################################################# @@ -1444,6 +1452,15 @@ $self->emit (changed => $self->{text}); } +sub set_text { + my ($self, $text) = @_; + + $self->{cursor} = length $text; + $self->_set_text ($text); + $self->check_size; + $self->update; +} + sub get_text { $_[0]{text} } @@ -1462,14 +1479,6 @@ $self->_set_text (delete $self->{text});#d# don't check for == inside _set_text } -sub set_text { - my ($self, $text) = @_; - - $self->{cursor} = length $text; - $self->_set_text ($text); - $self->update; -} - sub key_down { my ($self, $ev) = @_; @@ -1665,16 +1674,13 @@ $self->{fg} = $self->{active_fg}; } - 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; glColor 0, 0, 0, 1; - $tex[0]->draw_quad (0, 0, $self->{w}, $self->{h}); + $tex[0]->draw_quad_alpha (0, 0, $self->{w}, $self->{h}); glDisable GL_TEXTURE_2D; - glDisable GL_BLEND; $self->SUPER::_draw; } @@ -1731,16 +1737,13 @@ glColor @{ $FOCUS == $self ? $self->{active_fg} : $self->{fg} }; - glEnable GL_BLEND; glEnable GL_TEXTURE_2D; - glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; my $tex = $self->{state} ? $tex[1] : $tex[0]; - $tex->draw_quad (0, 0, $s, $s); + $tex->draw_quad_alpha (0, 0, $s, $s); glDisable GL_TEXTURE_2D; - glDisable GL_BLEND; } ############################################################################# @@ -1793,14 +1796,11 @@ ($w, $h) = ($h, $w); } - 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; - $tex->draw_quad (0, 0, $w, $h); + $tex->draw_quad_alpha (0, 0, $w, $h); - glDisable GL_BLEND; glDisable GL_TEXTURE_2D; } @@ -2102,18 +2102,15 @@ my $knob_a = $inner_pad_px + ($value - $page * 0.5); my $knob_b = $inner_pad_px + ($value + $page * 0.5); - 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; # draw background - $tex[1]->draw_quad (0, 0, $w, $h); + $tex[1]->draw_quad_alpha (0, 0, $w, $h); # draw handle - $tex[0]->draw_quad ($knob_a, 0, $knob_b - $knob_a, $h); + $tex[0]->draw_quad_alpha ($knob_a, 0, $knob_b - $knob_a, $h); - glDisable GL_BLEND; glDisable GL_TEXTURE_2D; } @@ -2134,7 +2131,7 @@ #font => default_font @_, - layout => (new CFClient::Layout), + layout => (new CFClient::Layout 1), par => [], height => 0, children => [ @@ -2162,7 +2159,7 @@ $layout->set_height ($self->{fontsize} * $::FONTSIZE); $layout->set_width ($self->{children}[0]{w}); - $layout->set_text ($text); + $layout->set_markup ($text); ($layout->size)[1] } @@ -2228,8 +2225,6 @@ glClearColor 0, 0, 0, 0; glClear GL_COLOR_BUFFER_BIT; - 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; @@ -2248,18 +2243,17 @@ my $h = $par->[0]; if ($y0 < $y + $h && $y < $y1) { - $layout->set_text ($par->[2]); + $layout->set_foreground (@{ $par->[1] }); + $layout->set_markup ($par->[2]); - glColor @{ $par->[1] }; my ($W, $H) = $layout->size; - CFClient::Texture->new_from_layout ($layout)->draw_quad (0, $y - $y0); + CFClient::Texture->new_from_layout ($layout)->draw_quad_alpha_premultiplied (0, $y - $y0); } $y += $h; } glDisable GL_TEXTURE_2D; - glDisable GL_BLEND; }; }); } @@ -2267,14 +2261,11 @@ sub _draw { my ($self) = @_; - glEnable GL_BLEND; - glBlendFunc GL_ONE, GL_ONE_MINUS_SRC_ALPHA; glEnable GL_TEXTURE_2D; glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; glColor 1, 1, 1, 1; - $self->{texture}->draw_quad (0, 0, $self->{children}[0]{w}, $self->{children}[0]{h}); + $self->{texture}->draw_quad_alpha_premultiplied (0, 0, $self->{children}[0]{w}, $self->{children}[0]{h}); glDisable GL_TEXTURE_2D; - glDisable GL_BLEND; $self->{children}[1]->draw; @@ -2379,9 +2370,14 @@ } sub set_markup { - my ($self, $text) = @_; + my ($self, $text, $font) = @_; - $self->{label} ||= new CFClient::UI::Label fontsize => 0.8, fg => [0, 0, 0]; + $self->{label} = new CFClient::UI::Label + fontsize => 0.8, + fg => [0, 0, 0], + font => ($font || $::FONT_PROP); + + $self->{label}->set_max_size ($::WIDTH * 0.3); $self->{label}->set_markup ($text); $self->add ($self->{label}); } @@ -2389,8 +2385,6 @@ 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) @@ -2461,14 +2455,11 @@ # TODO animation if ($tex) { - 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; glColor 1, 1, 1, 1; - $tex->draw_quad (0, 0, $self->{w}, $self->{h}); + $tex->draw_quad_alpha (0, 0, $self->{w}, $self->{h}); glDisable GL_TEXTURE_2D; - glDisable GL_BLEND; } } @@ -2655,6 +2646,71 @@ ############################################################################# +package CFClient::UI::Statusbox; + +our @ISA = CFClient::UI::VBox::; + +sub reorder { + my ($self) = @_; + my $NOW = time; + + while (my ($k, $v) = each %{ $self->{item} }) { + delete $self->{item}{$k} if $v->{timeout} < $NOW; + } + + my @widgets; + my @items = sort { $a->{time} <=> $b->{time} } values %{ $self->{item} }; + my $count = 10 + 1; + for my $item (@items) { + last unless --$count; + + push @widgets, $item->{label} ||= do { + # TODO: doesn't handle markup well (read as: at all) + my $short = delete $item->{text}; + for ($short) { + s/^\s+//; + s/\012.*//s; + my $len = int 30 / $item->{fontsize}; + substr $_, $len, length, "…" if $len < length; + } + + new CFClient::UI::Label + markup => $short, + tooltip => delete $item->{tooltip}, + fontsize => delete $item->{fontsize}, + color => delete $item->{color}, + can_events => 1, + can_hover => 1, + }; + } + + $self->clear; + $self->SUPER::add (@widgets); +} + +sub add { + my ($self, $text, %arg) = @_; + + my $item = { + time => time, + text => $text, + timeout => 60, + tooltip => $text, + fontsize => 0.8, + color => [0.8, 0.8, 0.8, 0.8], + %arg, + }; + + $item->{timeout} += time; + $item->{group} ||= $item+0; + + $item = $self->{item}{$item->{group}} ||= $item; + + $self->reorder; +} + +############################################################################# + package CFClient::UI::Root; our @ISA = CFClient::UI::Container::; @@ -2775,6 +2831,8 @@ : $widget->size_request; if ($w != $widget->{req_w} || $h != $widget->{req_h}) { + Carp::confess "$widget: size_request is negative" if $w < 0 || $h < 0;#d# + $widget->{req_w} = $w; $widget->{req_h} = $h; @@ -2790,6 +2848,9 @@ for (values %{delete $self->{size_alloc}}) { my ($widget, $w, $h) = @$_; + $w = 0 if $w < 0; + $h = 0 if $h < 0; + $widget->{w} = $w; $widget->{h} = $h; $widget->size_allocate ($w, $h);