--- deliantra/Deliantra-Client/DC/UI.pm 2006/04/30 13:10:46 1.183
+++ deliantra/Deliantra-Client/DC/UI.pm 2006/05/10 21:12:26 1.193
@@ -234,12 +234,7 @@
}
if ($self->{w} != $w || $self->{h} != $h) {
- $self->{w} = $w;
- $self->{h} = $h;
-
- $self->size_allocate ($w, $h);
- $self->update;
- $self->emit (size_allocate => $w, $h);
+ $CFClient::UI::ROOT->{size_alloc}{$self} = [$self, $w, $h];
}
}
@@ -257,7 +252,9 @@
$_->reconfigure
for $self->children;
- $_->check_size;
+ $self->check_size;
+ $CFClient::UI::ROOT->{size_alloc}{$self} = [$self, $self->{w}, $self->{h}];
+ $self->update;
}
sub set_max_size {
@@ -267,30 +264,18 @@
delete $self->{max_h}; $self->{max_h} = $h if $h;
}
-# return top left coordinates
-sub _topleft {
- my ($self, $x, $y) = @_;
-
- $self->{parent}
- or Carp::confess "no parent widget in _topleft\n";#d#
-
- $self->{parent}->_topleft ($x + $self->{x}, $y + $self->{y});
-}
-
# translate global coordinates to local coordinate system
sub coord2local {
my ($self, $x, $y) = @_;
- my ($X, $Y) = $self->_topleft;
- ($x - $X, $y - $Y)
+ $self->{parent}->coord2local ($x - $self->{x}, $y - $self->{y})
}
# translate local coordinates to global coordinate system
sub coord2global {
my ($self, $x, $y) = @_;
- my ($X, $Y) = $self->_topleft;
- ($x + $X, $y + $Y)
+ $self->{parent}->coord2global ($x + $self->{x}, $y + $self->{y})
}
sub focus_in {
@@ -398,32 +383,15 @@
my ($self, $parent) = @_;
Scalar::Util::weaken ($self->{parent} = $parent);
+
+ $self->check_size
+ unless exists $self->{req_w};
}
sub check_size {
my ($self) = @_;
- $self->{parent}
- or return 1;
-
- 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
- or $self->size_allocate (
- (List::Util::max $self->{w}, $w),
- (List::Util::max $self->{h}, $h),
- );
-
- 1
- } else {
- 0
- }
+ $CFClient::UI::ROOT->{check_size}{$self} = $self;
}
sub update {
@@ -530,18 +498,19 @@
}
sub add {
- my ($self, $child) = @_;
+ my ($self, @widgets) = @_;
- $child->set_parent ($self);
+ $_->set_parent ($self)
+ for @widgets;
use sort 'stable';
$self->{children} = [
sort { $a->{z} <=> $b->{z} }
- @{$self->{children}}, $child
+ @{$self->{children}}, @widgets
];
- $child->check_size;
+ $self->check_size;
$self->update;
}
@@ -741,6 +710,34 @@
$self->update;
}
+# hmm, this does not work for topleft of $self... but we should not ask for that
+sub coord2local {
+ my ($self, $x, $y) = @_;
+
+ $self->SUPER::coord2local ($x + $self->{view_x}, $y + $self->{view_y})
+}
+
+sub coord2global {
+ my ($self, $x, $y) = @_;
+
+ $x = List::Util::min $self->{w}, $x - $self->{view_x};
+ $y = List::Util::min $self->{h}, $y - $self->{view_y};
+
+ $self->SUPER::coord2global ($x, $y)
+}
+
+sub find_widget {
+ my ($self, $x, $y) = @_;
+
+ 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})
+ } else {
+ $self->CFClient::UI::Base::find_widget ($x, $y)
+ }
+}
+
sub _render {
my ($self) = @_;
@@ -1218,6 +1215,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;
@@ -1305,12 +1304,6 @@
$self->SUPER::update;
}
-sub reconfigure {
- my ($self) = @_;
-
- delete $self->{texture};
-}
-
sub set_text {
my ($self, $text) = @_;
@@ -1319,7 +1312,6 @@
$self->{layout}->set_text ($text);
- delete $self->{texture};
$self->update;
$self->check_size;
}
@@ -1332,7 +1324,6 @@
$self->{layout}->set_markup ($markup);
- delete $self->{texture};
$self->update;
$self->check_size;
}
@@ -1373,8 +1364,9 @@
$self->{fontsize} = $fontsize;
delete $self->{texture};
- $self->check_size;
+
$self->update;
+ $self->check_size;
}
sub _draw {
@@ -2466,6 +2458,7 @@
sub _draw {
my ($self) = @_;
+ return unless $::CONN;#d# manage and cache textures differently
my $tex = $::CONN->{texture}[$::CONN->{faceid}[$self->{face}]];
# TODO animation
@@ -2483,6 +2476,115 @@
#############################################################################
+package CFClient::UI::InventoryItem;
+
+our @ISA = CFClient::UI::HBox::;
+
+sub new {
+ my $class = shift;
+
+ my %args = @_;
+
+ my $item = delete $args{item};
+
+ my $desc = $item->{nrof} < 2
+ ? $item->{name}
+ : "$item->{nrof} $item->{name_pl}";
+
+
+ my $self = $class->SUPER::new (
+ can_hover => 1,
+ can_events => 1,
+ tooltip => (CFClient::UI::Label->escape ($desc)
+ . "\nleftclick - pick up\nmiddle click - apply\nrightclick - menu"),
+ connect_button_down => sub {
+ my ($self, $ev, $x, $y) = @_;
+
+ # todo: maybe put examine on 1? but should just be a tooltip :(
+ if ($ev->{button} == 1) {
+ $::CONN->send ("move $::CONN->{player}{tag} $item->{tag} 0");
+ } elsif ($ev->{button} == 2) {
+ $::CONN->send ("apply $item->{tag}");
+ } elsif ($ev->{button} == 3) {
+ CFClient::UI::Menu->new (
+ items => [
+ ["examine", sub { $::CONN->send ("examine $item->{tag}") }],
+ [
+ $item->{flags} & Crossfire::Protocol::F_LOCKED ? "lock" : "unlock",
+ sub { $::CONN->send ("lock $item->{tag}") },
+ ],
+ ["mark", sub { $::CONN->send ("mark $item->{tag}") }],
+ ["apply", sub { $::CONN->send ("apply $item->{tag}") }],
+ ["drop", sub { $::CONN->send ("move 0 $item->{tag} 0") }],
+ ],
+ )->popup ($ev);
+ }
+
+ 1
+ },
+ %args
+ );
+
+ $self->add (new CFClient::UI::Face
+ can_events => 0,
+ face => $item->{face},
+ anim => $item->{anim},
+ animspeed => $item->{animspeed},
+ );
+
+ $self->add (new CFClient::UI::Label
+ can_events => 0,
+ text => $desc,
+ );
+
+ $self
+}
+
+#############################################################################
+
+package CFClient::UI::Inventory;
+
+our @ISA = CFClient::UI::ScrolledWindow::;
+
+sub new {
+ my $class = shift;
+
+ my $self = $class->SUPER::new (
+ scrolled => (new CFClient::UI::VBox),
+ @_,
+ );
+
+ $self
+}
+
+sub set_items {
+ my ($self, $items) = @_;
+
+ $self->{scrolled}->clear;
+ return unless $items;
+
+ my @items = sort { $a->{type} <=> $b->{type} } @$items;
+
+ $self->{real_items} = \@items;
+
+ for my $item (@items) {
+ my $desc = $item->{nrof} < 2
+ ? $item->{name}
+ : "$item->{nrof} $item->{name_pl}";
+
+ $self->{scrolled}->add ($item->{widget} ||= new CFClient::UI::InventoryItem item => $item);
+ }
+
+# $range->{range} = [$self->{pos}, 0, $self->{max_pos}, $page];
+}
+
+sub size_request {
+ my ($self) = @_;
+ ($self->{req_w}, $self->{req_h});
+}
+
+#############################################################################
+
package CFClient::UI::Menu;
our @ISA = CFClient::UI::FancyFrame::;
@@ -2561,31 +2663,72 @@
use CFClient::OpenGL;
+sub new {
+ my $class = shift;
+
+ $class->SUPER::new (
+ @_,
+ )
+}
+
+sub configure {
+ my ($self, $x, $y, $w, $h) = @_;
+
+ $self->{w} = $w;
+ $self->{h} = $h;
+}
+
sub check_size {
my ($self) = @_;
- $self->configure (0, 0, $::WIDTH, $::HEIGHT);
+ $self->size_allocate ($self->{w}, $self->{h})
+ if $self->{w};
}
sub size_request {
- ($::WIDTH, $::HEIGHT)
+ my ($self) = @_;
+
+ ($self->{w}, $self->{h})
}
-sub configure {
- my ($self, $x, $y, $w, $h) = @_;
+sub size_allocate {
+ my ($self, $w, $h) = @_;
- $self->SUPER::configure ($x, $y, $w, $h);
+ my $old_w = $self->{old_w};
+ my $old_h = $self->{old_h};
- for my $child (@{$self->{children}}) {
+ if ($old_w && $old_h) {
+ for my $child ($self->children) {
+ $child->{x} = int 0.5 + $child->{x} * $w / $old_w;
+ $child->{w} = int 0.5 + $child->{w} * $w / $old_w;
+ $child->{req_w} = int 0.5 + $child->{req_w} * $w / $old_w if exists $child->{req_w};
+ $child->{user_w} = int 0.5 + $child->{user_w} * $w / $old_w if exists $child->{user_w};
+ $child->{y} = int 0.5 + $child->{y} * $h / $old_h;
+ $child->{h} = int 0.5 + $child->{h} * $h / $old_h;
+ $child->{req_h} = int 0.5 + $child->{req_h} * $h / $old_h if exists $child->{req_h};
+ $child->{user_h} = int 0.5 + $child->{user_h} * $h / $old_h if exists $child->{user_h};
+ }
+ }
+
+ 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);
+ $child->configure ($X, $Y, $W, $H);
}
+
+ $self->{old_w} = $w;
+ $self->{old_h} = $h;
+}
+
+sub coord2local {
+ my ($self, $x, $y) = @_;
+
+ ($x, $y)
}
-sub _topleft {
+sub coord2global {
my ($self, $x, $y) = @_;
($x, $y)
@@ -2595,13 +2738,13 @@
my ($self) = @_;
$self->check_size;
- ::refresh ();
+ $::WANT_REFRESH++;
}
sub add {
my ($self, $child) = @_;
- # integerize window positions
+ # integerise window positions
$child->{x} = int $child->{x};
$child->{y} = int $child->{y};
@@ -2614,129 +2757,69 @@
$self->{refresh_hook}{$id} = $cb;
}
-sub draw {
+sub draw {
my ($self) = @_;
- while (my $rcb = delete $self->{refresh_hook}) {
- $_->() for values %$rcb;
- }
-
- glViewport 0, 0, $::WIDTH, $::HEIGHT;
- glClearColor +($::CFG->{fow_intensity}) x 3, 1;
- glClear GL_COLOR_BUFFER_BIT;
-
- glMatrixMode GL_PROJECTION;
- glLoadIdentity;
- glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000 , 10000;
- glMatrixMode GL_MODELVIEW;
- glLoadIdentity;
+ if ($self->{check_size}) {
+ my @queue = ([], []);
- $self->_draw;
-}
-
-#############################################################################
-
-package CFClient::UI::InventoryItem;
-
-our @ISA = CFClient::UI::HBox::;
-
-sub new {
- my $class = shift;
-
- my %args = @_;
-
- my $item = $args{item};
-
- my $desc = $item->{nrof} < 2
- ? $item->{name}
- : "$item->{nrof} $item->{name_pl}";
-
-
- my $self = $class->SUPER::new (
- can_hover => 1,
- can_events => 1,
- tooltip => (CFClient::UI::Label->escape ($desc)
- . "\nleftclick - pick up\nmiddle click - apply\nrightclick - menu"),
- connect_button_down => sub {
- my ($self, $ev, $x, $y) = @_;
-
- # todo: maybe put examine on 1? but should just be a tooltip :(
- if ($ev->{button} == 1) {
- $::CONN->send ("move $::CONN->{player}{tag} $item->{tag} 0");
- } elsif ($ev->{button} == 2) {
- $::CONN->send ("apply $item->{tag}");
- } elsif ($ev->{button} == 3) {
- CFClient::UI::Menu->new (
- items => [
- ["examine", sub { $::CONN->send ("examine $item->{tag}") }],
- [
- $item->{flags} & Crossfire::Protocol::F_LOCKED ? "lock" : "unlock",
- sub { $::CONN->send ("lock $item->{tag}") },
- ],
- ["mark", sub { $::CONN->send ("mark $item->{tag}") }],
- ["apply", sub { $::CONN->send ("apply $item->{tag}") }],
- ["drop", sub { $::CONN->send ("move 0 $item->{tag} 0") }],
- ],
- )->popup ($ev);
+ for (;;) {
+ if ($self->{check_size}) {
+ # heuristic: check containers last
+ push @{ $queue[ ! ! $_->isa ("CFClient::UI::Container") ] }, $_
+ for values %{delete $self->{check_size}}
}
- 1
- },
- %args
- );
- $self->add(new CFClient::UI::Face
- can_events => 0,
- face => $item->{face},
- anim => $item->{anim},
- animspeed => $item->{animspeed});
- $self->add(new CFClient::UI::Label
- can_events => 0,
- text => $desc);
-
- $self
-}
+ my $widget = (pop @{ $queue[0] }) || (pop @{ $queue[1] }) || last;
-#############################################################################
+ my ($w, $h) = $widget->{user_w} && $widget->{user_h}
+ ? @$widget{qw(user_w user_h)}
+ : $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;
-package CFClient::UI::Inventory;
+ $self->{size_alloc}{$widget} = [$widget, $widget->{w}, $widget->{h}];
-our @ISA = CFClient::UI::ScrolledWindow::;
-
-sub new {
- my $class = shift;
-
- my $self = $class->SUPER::new (
- scrolled => (new CFClient::UI::VBox),
- @_,
- );
-
- $self
-}
-
-sub set_items {
- my ($self, $items) = @_;
-
- $self->{scrolled}->clear;
- return unless $items;
+ $widget->{parent}->check_size
+ if $widget->{parent};
+ }
+ }
+ }
- my @items = sort { $a->{type} <=> $b->{type} } @$items;
+ while ($self->{size_alloc}) {
+ for (values %{delete $self->{size_alloc}}) {
+ my ($widget, $w, $h) = @$_;
- $self->{real_items} = \@items;
+ $w = 0 if $w < 0;
+ $h = 0 if $h < 0;
- for my $item (@items) {
- my $desc = $item->{nrof} < 2
- ? $item->{name}
- : "$item->{nrof} $item->{name_pl}";
+ $widget->{w} = $w;
+ $widget->{h} = $h;
+ $widget->size_allocate ($w, $h);
+ $widget->emit (size_allocate => $w, $h);
+ }
+ }
- $self->{scrolled}->add (new CFClient::UI::InventoryItem item => $item);
+ while ($self->{refresh_hook}) {
+ $_->()
+ for values %{delete $self->{refresh_hook}};
}
-# $range->{range} = [$self->{pos}, 0, $self->{max_pos}, $page];
-}
+ glViewport 0, 0, $::WIDTH, $::HEIGHT;
+ glClearColor +($::CFG->{fow_intensity}) x 3, 1;
+ glClear GL_COLOR_BUFFER_BIT;
-sub size_request {
- my ($self) = @_;
- ($self->{req_w}, $self->{req_h});
+ glMatrixMode GL_PROJECTION;
+ glLoadIdentity;
+ glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000 , 10000;
+ glMatrixMode GL_MODELVIEW;
+ glLoadIdentity;
+
+ $self->_draw;
}
#############################################################################