ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/DC/UI.pm
(Generate patch)

Comparing deliantra/Deliantra-Client/DC/UI.pm (file contents):
Revision 1.331 by root, Sun Jul 23 04:46:02 2006 UTC vs.
Revision 1.339 by root, Sun Jul 30 12:15:19 2006 UTC

96 96
97sub feed_sdl_button_down_event { 97sub feed_sdl_button_down_event {
98 my ($ev) = @_; 98 my ($ev) = @_;
99 my ($x, $y) = ($ev->{x}, $ev->{y}); 99 my ($x, $y) = ($ev->{x}, $ev->{y});
100 100
101 unless ($BUTTON_STATE) { 101 $BUTTON_STATE |= 1 << ($ev->{button} - 1);
102
103 unless ($GRAB) {
102 my $widget = $ROOT->find_widget ($x, $y); 104 my $widget = $ROOT->find_widget ($x, $y);
103 105
104 $GRAB = $widget; 106 $GRAB = $widget;
105 $GRAB->update if $GRAB; 107 $GRAB->update if $GRAB;
106 108
107 $TOOLTIP_WATCHER->cb->(); 109 $TOOLTIP_WATCHER->cb->();
108 } 110 }
109
110 $BUTTON_STATE |= 1 << ($ev->{button} - 1);
111 111
112 if ($GRAB) { 112 if ($GRAB) {
113 if ($ev->{button} == 4 || $ev->{button} == 5) { 113 if ($ev->{button} == 4 || $ev->{button} == 5) {
114 # mousewheel 114 # mousewheel
115 $ev->{dx} = 0; 115 $ev->{dx} = 0;
367 my ($self, $x, $y, $w, $h) = @_; 367 my ($self, $x, $y, $w, $h) = @_;
368 368
369 if ($self->{aspect}) { 369 if ($self->{aspect}) {
370 my ($ow, $oh) = ($w, $h); 370 my ($ow, $oh) = ($w, $h);
371 371
372 $w = List::Util::min $w, int $h * $self->{aspect}; 372 $w = List::Util::min $w, CFClient::ceil $h * $self->{aspect};
373 $h = List::Util::min $h, int $w / $self->{aspect}; 373 $h = List::Util::min $h, CFClient::ceil $w / $self->{aspect};
374 374
375 # use alignment to adjust x, y 375 # use alignment to adjust x, y
376 376
377 $x += int 0.5 * ($ow - $w); 377 $x += int 0.5 * ($ow - $w);
378 $y += int 0.5 * ($oh - $h); 378 $y += int 0.5 * ($oh - $h);
437} 437}
438 438
439# translate local coordinates to global coordinate system 439# translate local coordinates to global coordinate system
440sub coord2global { 440sub coord2global {
441 my ($self, $x, $y) = @_; 441 my ($self, $x, $y) = @_;
442
443 Carp::confess unless $self->{parent};#d#
442 444
443 $self->{parent}->coord2global ($x + $self->{x}, $y + $self->{y}) 445 $self->{parent}->coord2global ($x + $self->{x}, $y + $self->{y})
444} 446}
445 447
446sub invoke_focus_in { 448sub invoke_focus_in {
494 496
495sub connect { 497sub connect {
496 my ($self, $signal, $cb) = @_; 498 my ($self, $signal, $cb) = @_;
497 499
498 push @{ $self->{signal_cb}{$signal} }, $cb; 500 push @{ $self->{signal_cb}{$signal} }, $cb;
501
502 defined wantarray and CFClient::guard {
503 @{ $self->{signal_cb}{$signal} } = grep $_ != $cb,
504 @{ $self->{signal_cb}{$signal} };
505 }
499} 506}
500 507
501my %has_coords = ( 508my %has_coords = (
502 button_down => 1, 509 button_down => 1,
503 button_up => 1, 510 button_up => 1,
506); 513);
507 514
508sub emit { 515sub emit {
509 my ($self, $signal, @args) = @_; 516 my ($self, $signal, @args) = @_;
510 517
518 # I do not really like this solution, but I dislike duplication
519 # and needlessly verbose code, too.
511 my @append 520 my @append
512 = $has_coords{$signal} 521 = $has_coords{$signal}
513 ? $args[0]->xy ($self) 522 ? $args[0]->xy ($self)
514 : (); 523 : ();
515 524
722 if $children; 731 if $children;
723 732
724 $self 733 $self
725} 734}
726 735
736sub realloc {
737 my ($self) = @_;
738
739 $self->{force_realloc} = 1;
740 $self->{force_size_alloc} = 1;
741 $self->SUPER::realloc;
742}
743
727sub add { 744sub add {
728 my ($self, @widgets) = @_; 745 my ($self, @widgets) = @_;
729 746
730 $_->set_parent ($self) 747 $_->set_parent ($self)
731 for @widgets; 748 for @widgets;
1279 $self->{motion}->($ev, $x, $y) if $self->{motion}; 1296 $self->{motion}->($ev, $x, $y) if $self->{motion};
1280 1297
1281 ! ! $self->{motion} 1298 ! ! $self->{motion}
1282} 1299}
1283 1300
1301sub invoke_visibility_change {
1302 my ($self, $visible) = @_;
1303
1304 delete $self->{motion} unless $visible;
1305
1306 0
1307}
1308
1284sub _draw { 1309sub _draw {
1285 my ($self) = @_; 1310 my ($self) = @_;
1286 1311
1287 my $child = $self->{children}[0]; 1312 my $child = $self->{children}[0];
1288 1313
1347sub children { 1372sub children {
1348 grep $_, map @$_, grep $_, @{ $_[0]{children} } 1373 grep $_, map @$_, grep $_, @{ $_[0]{children} }
1349} 1374}
1350 1375
1351sub add { 1376sub add {
1352 my ($self, $x, $y, $child) = @_; 1377 my ($self) = shift;
1353 1378
1379 while (@_) {
1380 my ($x, $y, $child) = splice @_, 0, 3, ();
1354 $child->set_parent ($self); 1381 $child->set_parent ($self);
1355 $self->{children}[$y][$x] = $child; 1382 $self->{children}[$y][$x] = $child;
1383 }
1356 1384
1385 $self->{force_realloc} = 1;
1386 $self->{force_size_alloc} = 1;
1357 $self->realloc; 1387 $self->realloc;
1358} 1388}
1359 1389
1360sub remove { 1390sub remove {
1361 my ($self, $child) = @_; 1391 my ($self, $child) = @_;
1613 } 1643 }
1614 1644
1615 $self 1645 $self
1616} 1646}
1617 1647
1618sub escape($) {
1619 local $_ = $_[0];
1620
1621 s/&/&amp;/g;
1622 s/>/&gt;/g;
1623 s/</&lt;/g;
1624
1625 $_
1626}
1627
1628sub update { 1648sub update {
1629 my ($self) = @_; 1649 my ($self) = @_;
1630 1650
1631 delete $self->{texture}; 1651 delete $self->{texture};
1632 $self->SUPER::update; 1652 $self->SUPER::update;
2041 $self->SUPER::_draw; 2061 $self->SUPER::_draw;
2042} 2062}
2043 2063
2044############################################################################# 2064#############################################################################
2045 2065
2066package CFClient::UI::CheckBox;
2067
2068our @ISA = CFClient::UI::DrawBG::;
2069
2070my @tex =
2071 map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 }
2072 qw(c1_checkbox_bg.png c1_checkbox_active.png);
2073
2074use CFClient::OpenGL;
2075
2076sub new {
2077 my $class = shift;
2078
2079 $class->SUPER::new (
2080 padding_x => 2,
2081 padding_y => 2,
2082 fg => [1, 1, 1],
2083 active_fg => [1, 1, 0],
2084 bg => [0, 0, 0, 0.2],
2085 active_bg => [1, 1, 1, 0.5],
2086 state => 0,
2087 can_hover => 1,
2088 @_
2089 )
2090}
2091
2092sub size_request {
2093 my ($self) = @_;
2094
2095 (6) x 2
2096}
2097
2098sub toggle {
2099 my ($self) = @_;
2100
2101 $self->{state} = !$self->{state};
2102 $self->emit (changed => $self->{state});
2103 $self->update;
2104}
2105
2106sub invoke_button_down {
2107 my ($self, $ev, $x, $y) = @_;
2108
2109 if ($x >= $self->{padding_x} && $x < $self->{w} - $self->{padding_x}
2110 && $y >= $self->{padding_y} && $y < $self->{h} - $self->{padding_y}) {
2111 $self->toggle;
2112 } else {
2113 return 0
2114 }
2115
2116 1
2117}
2118
2119sub _draw {
2120 my ($self) = @_;
2121
2122 $self->SUPER::_draw;
2123
2124 glTranslate $self->{padding_x} + 0.375, $self->{padding_y} + 0.375, 0;
2125
2126 my ($w, $h) = @$self{qw(w h)};
2127
2128 my $s = List::Util::min $w - $self->{padding_x} * 2, $h - $self->{padding_y} * 2;
2129
2130 glColor @{ $FOCUS == $self ? $self->{active_fg} : $self->{fg} };
2131
2132 my $tex = $self->{state} ? $tex[1] : $tex[0];
2133
2134 glEnable GL_TEXTURE_2D;
2135 $tex->draw_quad_alpha (0, 0, $s, $s);
2136 glDisable GL_TEXTURE_2D;
2137}
2138
2139#############################################################################
2140
2141package CFClient::UI::Image;
2142
2143our @ISA = CFClient::UI::Base::;
2144
2145use CFClient::OpenGL;
2146
2147our %texture_cache;
2148
2149sub new {
2150 my $class = shift;
2151
2152 my $self = $class->SUPER::new (
2153 can_events => 0,
2154 @_,
2155 );
2156
2157 $self->{path} || $self->{tex}
2158 or Carp::croak "'path' or 'tex' attributes required";
2159
2160 $self->{tex} ||= $texture_cache{$self->{path}} ||=
2161 new_from_file CFClient::Texture CFClient::find_rcfile $self->{path}, mipmap => 1;
2162
2163 Scalar::Util::weaken $texture_cache{$self->{path}};
2164
2165 $self->{aspect} ||= $self->{tex}{w} / $self->{tex}{h};
2166
2167 $self
2168}
2169
2170sub STORABLE_freeze {
2171 my ($self, $cloning) = @_;
2172
2173 $self->{path}
2174 or die "cannot serialise CFClient::UI::Image on non-loadable images\n";
2175
2176 $self->{path}
2177}
2178
2179sub STORABLE_attach {
2180 my ($self, $cloning, $path) = @_;
2181
2182 $self->new (path => $path)
2183}
2184
2185sub size_request {
2186 my ($self) = @_;
2187
2188 ($self->{tex}{w}, $self->{tex}{h})
2189}
2190
2191sub _draw {
2192 my ($self) = @_;
2193
2194 my $tex = $self->{tex};
2195
2196 my ($w, $h) = ($self->{w}, $self->{h});
2197
2198 if ($self->{rot90}) {
2199 glRotate 90, 0, 0, 1;
2200 glTranslate 0, -$self->{w}, 0;
2201
2202 ($w, $h) = ($h, $w);
2203 }
2204
2205 glEnable GL_TEXTURE_2D;
2206 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE;
2207
2208 $tex->draw_quad (0, 0, $w, $h);
2209
2210 glDisable GL_TEXTURE_2D;
2211}
2212
2213#############################################################################
2214
2046package CFClient::UI::ImageButton; 2215package CFClient::UI::ImageButton;
2047 2216
2048our @ISA = CFClient::UI::Image::; 2217our @ISA = CFClient::UI::Image::;
2049 2218
2050use CFClient::OpenGL; 2219use CFClient::OpenGL;
2073 $self->emit ("activate") 2242 $self->emit ("activate")
2074 if $x >= 0 && $x < $self->{w} 2243 if $x >= 0 && $x < $self->{w}
2075 && $y >= 0 && $y < $self->{h}; 2244 && $y >= 0 && $y < $self->{h};
2076 2245
2077 1 2246 1
2078}
2079
2080#############################################################################
2081
2082package CFClient::UI::CheckBox;
2083
2084our @ISA = CFClient::UI::DrawBG::;
2085
2086my @tex =
2087 map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 }
2088 qw(c1_checkbox_bg.png c1_checkbox_active.png);
2089
2090use CFClient::OpenGL;
2091
2092sub new {
2093 my $class = shift;
2094
2095 $class->SUPER::new (
2096 padding_x => 2,
2097 padding_y => 2,
2098 fg => [1, 1, 1],
2099 active_fg => [1, 1, 0],
2100 bg => [0, 0, 0, 0.2],
2101 active_bg => [1, 1, 1, 0.5],
2102 state => 0,
2103 can_hover => 1,
2104 @_
2105 )
2106}
2107
2108sub size_request {
2109 my ($self) = @_;
2110
2111 (6) x 2
2112}
2113
2114sub toggle {
2115 my ($self) = @_;
2116
2117 $self->{state} = !$self->{state};
2118 $self->emit (changed => $self->{state});
2119 $self->update;
2120}
2121
2122sub invoke_button_down {
2123 my ($self, $ev, $x, $y) = @_;
2124
2125 if ($x >= $self->{padding_x} && $x < $self->{w} - $self->{padding_x}
2126 && $y >= $self->{padding_y} && $y < $self->{h} - $self->{padding_y}) {
2127 $self->toggle;
2128 } else {
2129 return 0
2130 }
2131
2132 1
2133}
2134
2135sub _draw {
2136 my ($self) = @_;
2137
2138 $self->SUPER::_draw;
2139
2140 glTranslate $self->{padding_x} + 0.375, $self->{padding_y} + 0.375, 0;
2141
2142 my ($w, $h) = @$self{qw(w h)};
2143
2144 my $s = List::Util::min $w - $self->{padding_x} * 2, $h - $self->{padding_y} * 2;
2145
2146 glColor @{ $FOCUS == $self ? $self->{active_fg} : $self->{fg} };
2147
2148 my $tex = $self->{state} ? $tex[1] : $tex[0];
2149
2150 glEnable GL_TEXTURE_2D;
2151 $tex->draw_quad_alpha (0, 0, $s, $s);
2152 glDisable GL_TEXTURE_2D;
2153}
2154
2155#############################################################################
2156
2157package CFClient::UI::Image;
2158
2159our @ISA = CFClient::UI::Base::;
2160
2161use CFClient::OpenGL;
2162
2163our %texture_cache;
2164
2165sub new {
2166 my $class = shift;
2167
2168 my $self = $class->SUPER::new (
2169 can_events => 0,
2170 @_,
2171 );
2172
2173 $self->{path} || $self->{tex}
2174 or Carp::croak "'path' or 'tex' attributes required";
2175
2176 $self->{tex} ||= $texture_cache{$self->{path}} ||=
2177 new_from_file CFClient::Texture CFClient::find_rcfile $self->{path}, mipmap => 1;
2178
2179 Scalar::Util::weaken $texture_cache{$self->{path}};
2180
2181 $self->{aspect} ||= $self->{tex}{w} / $self->{tex}{h};
2182
2183 $self
2184}
2185
2186sub size_request {
2187 my ($self) = @_;
2188
2189 ($self->{tex}{w}, $self->{tex}{h})
2190}
2191
2192sub _draw {
2193 my ($self) = @_;
2194
2195 my $tex = $self->{tex};
2196
2197 my ($w, $h) = ($self->{w}, $self->{h});
2198
2199 if ($self->{rot90}) {
2200 glRotate 90, 0, 0, 1;
2201 glTranslate 0, -$self->{w}, 0;
2202
2203 ($w, $h) = ($h, $w);
2204 }
2205
2206 glEnable GL_TEXTURE_2D;
2207 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE;
2208
2209 $tex->draw_quad_alpha (0, 0, $w, $h);
2210
2211 glDisable GL_TEXTURE_2D;
2212} 2247}
2213 2248
2214############################################################################# 2249#############################################################################
2215 2250
2216package CFClient::UI::VGauge; 2251package CFClient::UI::VGauge;
2506sub invoke_mouse_wheel { 2541sub invoke_mouse_wheel {
2507 my ($self, $ev) = @_; 2542 my ($self, $ev) = @_;
2508 2543
2509 my $delta = $self->{vertical} ? $ev->{dy} : $ev->{dx}; 2544 my $delta = $self->{vertical} ? $ev->{dy} : $ev->{dx};
2510 2545
2511 $self->set_value ($self->{range}[0] + $delta * $self->{range}[3] * 0.1); 2546 $self->set_value ($self->{range}[0] + $delta * $self->{range}[3] * 0.2);
2512 2547
2513 ! ! $delta 2548 ! ! $delta
2514} 2549}
2515 2550
2516sub update { 2551sub update {
2728 $self->{height} = 0; 2763 $self->{height} = 0;
2729 $self->{children}[1]->set_range ([0, 0, 0, 1, 1]); 2764 $self->{children}[1]->set_range ([0, 0, 0, 1, 1]);
2730} 2765}
2731 2766
2732sub add_paragraph { 2767sub add_paragraph {
2733 my ($self, $color, $para, $indent) = @_; 2768 my $self = shift;
2734 2769
2735 my ($text, @w) = ref $para ? @$para : $para; 2770 for my $para (@_) {
2736
2737 $para = { 2771 $para = {
2772 fg => [1, 1, 1, 1],
2773 indent => 0,
2774 markup => "",
2775 widget => [],
2776 ref $para ? %$para : (markup => $para),
2738 w => 1e10, 2777 w => 1e10,
2739 wrapped => 1, 2778 wrapped => 1,
2740 fg => $color,
2741 indent => $indent,
2742 markup => $text,
2743 widget => \@w,
2744 }; 2779 };
2745 2780
2746 $self->add (@w) if @w; 2781 $self->add (@{ $para->{widget} }) if @{ $para->{widget} };
2747 push @{$self->{par}}, $para; 2782 push @{$self->{par}}, $para;
2783 }
2748 2784
2749 $self->{need_reflow}++; 2785 $self->{need_reflow}++;
2750 $self->update; 2786 $self->update;
2751} 2787}
2752 2788
2986 3022
2987 $self->{root}->on_post_alloc ("move_$self" => sub { 3023 $self->{root}->on_post_alloc ("move_$self" => sub {
2988 my $widget = $self->{owner} 3024 my $widget = $self->{owner}
2989 or return; 3025 or return;
2990 3026
3027 if ($widget->{visible}) {
2991 my ($x, $y) = $widget->coord2global ($widget->{w}, 0); 3028 my ($x, $y) = $widget->coord2global ($widget->{w}, 0);
2992 3029
2993 ($x, $y) = $widget->coord2global (-$self->{w}, 0) 3030 ($x, $y) = $widget->coord2global (-$self->{w}, 0)
2994 if $x + $self->{w} > $self->{root}{w}; 3031 if $x + $self->{w} > $self->{root}{w};
2995 3032
2996 $self->move_abs ($x, $y); 3033 $self->move_abs ($x, $y);
3034 } else {
3035 $self->hide;
3036 }
2997 }); 3037 });
2998} 3038}
2999 3039
3000sub _draw { 3040sub _draw {
3001 my ($self) = @_; 3041 my ($self) = @_;
3027 3067
3028############################################################################# 3068#############################################################################
3029 3069
3030package CFClient::UI::Face; 3070package CFClient::UI::Face;
3031 3071
3032our @ISA = CFClient::UI::Base::; 3072our @ISA = CFClient::UI::DrawBG::;
3033 3073
3034use CFClient::OpenGL; 3074use CFClient::OpenGL;
3035 3075
3036sub new { 3076sub new {
3037 my $class = shift; 3077 my $class = shift;
3073 3113
3074sub _draw { 3114sub _draw {
3075 my ($self) = @_; 3115 my ($self) = @_;
3076 3116
3077 return unless $::CONN; 3117 return unless $::CONN;
3118
3119 $self->SUPER::_draw;
3078 3120
3079 my $face; 3121 my $face;
3080 3122
3081 if ($self->{frame}) { 3123 if ($self->{frame}) {
3082 my $anim = $::CONN->{anim}[$self->{anim}]; 3124 my $anim = $::CONN->{anim}[$self->{anim}];
3329 $self->emit (page_changed => $self->{multiplexer}{current}); 3371 $self->emit (page_changed => $self->{multiplexer}{current});
3330} 3372}
3331 3373
3332############################################################################# 3374#############################################################################
3333 3375
3334package CFClient::UI::Combobox; 3376package CFClient::UI::Selector;
3335 3377
3336use utf8; 3378use utf8;
3337 3379
3338our @ISA = CFClient::UI::Button::; 3380our @ISA = CFClient::UI::Button::;
3339 3381
3539sub new { 3581sub new {
3540 my $class = shift; 3582 my $class = shift;
3541 3583
3542 my $self = $class->SUPER::new ( 3584 my $self = $class->SUPER::new (
3543 col_expand => [0, 1, 0], 3585 col_expand => [0, 1, 0],
3586 items => [],
3544 @_, 3587 @_,
3545 ); 3588 );
3546 3589
3590 $self->set_sort_order (undef);
3591
3547 $self 3592 $self
3593}
3594
3595sub update_items {
3596 my ($self) = @_;
3597
3598 $self->clear;
3599
3600 my @item = $self->{sort}->(@{ $self->{items} });
3601
3602 my @adds;
3603 my $row = 0;
3604 for my $item ($self->{sort}->(@{ $self->{items} })) {
3605 CFClient::Item::update_widgets $item;
3606
3607 push @adds, 0, $row, $item->{face_widget};
3608 push @adds, 1, $row, $item->{desc_widget};
3609 push @adds, 2, $row, $item->{weight_widget};
3610
3611 $row++;
3612 }
3613
3614 $self->add (@adds);
3615}
3616
3617sub set_sort_order {
3618 my ($self, $order) = @_;
3619
3620 $self->{sort} = $order ||= sub {
3621 sort {
3622 $a->{type} <=> $b->{type}
3623 or $a->{name} cmp $b->{name}
3624 } @_
3625 };
3626
3627 $self->update_items;
3548} 3628}
3549 3629
3550sub set_items { 3630sub set_items {
3551 my ($self, $items) = @_; 3631 my ($self, $items) = @_;
3552 3632
3553 $self->clear; 3633 $self->{items} = [$items ? values %$items : ()];
3554 return unless $items; 3634 $self->update_items;
3555
3556 my @items = sort {
3557 ($a->{type} <=> $b->{type})
3558 or ($a->{name} cmp $b->{name})
3559 } values %$items;
3560
3561 $self->{real_items} = \@items;
3562
3563 my $row = 0;
3564 for my $item (@items) {
3565 CFClient::Item::update_widgets $item;
3566
3567 $self->add (0, $row, $item->{face_widget});
3568 $self->add (1, $row, $item->{desc_widget});
3569 $self->add (2, $row, $item->{weight_widget});
3570
3571 $row++;
3572 }
3573} 3635}
3574 3636
3575############################################################################# 3637#############################################################################
3576 3638
3577package CFClient::UI::SpellList; 3639package CFClient::UI::SpellList;
3889 $h = 0 if $h < 0; 3951 $h = 0 if $h < 0;
3890 3952
3891 $w = max $widget->{min_w}, $w; 3953 $w = max $widget->{min_w}, $w;
3892 $h = max $widget->{min_h}, $h; 3954 $h = max $widget->{min_h}, $h;
3893 3955
3956# $w = min $self->{w} - $widget->{x}, $w if $self->{w};
3957# $h = min $self->{h} - $widget->{y}, $h if $self->{h};
3958
3894 $w = min $widget->{max_w}, $w if exists $widget->{max_w}; 3959 $w = min $widget->{max_w}, $w if exists $widget->{max_w};
3895 $h = min $widget->{max_h}, $h if exists $widget->{max_h}; 3960 $h = min $widget->{max_h}, $h if exists $widget->{max_h};
3896 3961
3897 $w = int $w + 0.5; 3962 $w = int $w + 0.5;
3898 $h = int $h + 0.5; 3963 $h = int $h + 0.5;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines