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.258 by root, Tue May 30 02:55:45 2006 UTC vs.
Revision 1.268 by root, Thu Jun 1 05:04:41 2006 UTC

40 40
41 $LAYOUT = $layout; 41 $LAYOUT = $layout;
42} 42}
43 43
44sub check_tooltip { 44sub check_tooltip {
45 return if $ENV{CFPLUS_DEBUG} & 8;
46
45 if (!$GRAB) { 47 if (!$GRAB) {
46 for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) { 48 for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) {
47 if (length $widget->{tooltip}) { 49 if (length $widget->{tooltip}) {
48
49 if ($TOOLTIP->{owner} != $widget) { 50 if ($TOOLTIP->{owner} != $widget) {
50 $TOOLTIP->hide; 51 $TOOLTIP->hide;
51 52
52 $TOOLTIP->{owner} = $widget; 53 $TOOLTIP->{owner} = $widget;
53 54
170sub rescale_widgets { 171sub rescale_widgets {
171 my ($sx, $sy) = @_; 172 my ($sx, $sy) = @_;
172 173
173 for my $widget (values %WIDGET) { 174 for my $widget (values %WIDGET) {
174 if ($widget->{is_toplevel}) { 175 if ($widget->{is_toplevel}) {
175 $widget->{x} += $widget->{w} * 0.5 if $widget->{x} =~ /^[0-9.]+$/; 176 $widget->{x} += int $widget->{w} * 0.5 if $widget->{x} =~ /^[0-9.]+$/;
176 $widget->{y} += $widget->{h} * 0.5 if $widget->{y} =~ /^[0-9.]+$/; 177 $widget->{y} += int $widget->{h} * 0.5 if $widget->{y} =~ /^[0-9.]+$/;
177 178
178 $widget->{x} = int 0.5 + $widget->{x} * $sx if $widget->{x} =~ /^[0-9.]+$/; 179 $widget->{x} = int 0.5 + $widget->{x} * $sx if $widget->{x} =~ /^[0-9.]+$/;
179 $widget->{w} = int 0.5 + $widget->{w} * $sx if exists $widget->{w}; 180 $widget->{w} = int 0.5 + $widget->{w} * $sx if exists $widget->{w};
180 $widget->{force_w} = int 0.5 + $widget->{force_w} * $sx if exists $widget->{force_w}; 181 $widget->{force_w} = int 0.5 + $widget->{force_w} * $sx if exists $widget->{force_w};
181 $widget->{y} = int 0.5 + $widget->{y} * $sy if $widget->{y} =~ /^[0-9.]+$/; 182 $widget->{y} = int 0.5 + $widget->{y} * $sy if $widget->{y} =~ /^[0-9.]+$/;
182 $widget->{h} = int 0.5 + $widget->{h} * $sy if exists $widget->{h}; 183 $widget->{h} = int 0.5 + $widget->{h} * $sy if exists $widget->{h};
183 $widget->{force_h} = int 0.5 + $widget->{force_h} * $sy if exists $widget->{force_h}; 184 $widget->{force_h} = int 0.5 + $widget->{force_h} * $sy if exists $widget->{force_h};
184 185
185 $widget->{x} -= $widget->{w} * 0.5 if $widget->{x} =~ /^[0-9.]+$/; 186 $widget->{x} -= int $widget->{w} * 0.5 if $widget->{x} =~ /^[0-9.]+$/;
186 $widget->{y} -= $widget->{h} * 0.5 if $widget->{y} =~ /^[0-9.]+$/; 187 $widget->{y} -= int $widget->{h} * 0.5 if $widget->{y} =~ /^[0-9.]+$/;
187 188
188 } 189 }
189 } 190 }
190 191
191 reconfigure_widgets; 192 reconfigure_widgets;
219 $self->connect ($1 => delete $self->{$_}); 220 $self->connect ($1 => delete $self->{$_});
220 } 221 }
221 } 222 }
222 223
223 if (my $layout = $CFClient::UI::LAYOUT->{$self->{name}}) { 224 if (my $layout = $CFClient::UI::LAYOUT->{$self->{name}}) {
224 $self->{x} = $layout->{x} * $CFClient::UI::ROOT->{w} if exists $layout->{x}; 225 $self->{x} = $layout->{x} * $CFClient::UI::ROOT->{alloc_w} if exists $layout->{x};
225 $self->{y} = $layout->{y} * $CFClient::UI::ROOT->{h} if exists $layout->{y}; 226 $self->{y} = $layout->{y} * $CFClient::UI::ROOT->{alloc_h} if exists $layout->{y};
226 $self->{force_w} = $layout->{w} * $CFClient::UI::ROOT->{w} if exists $layout->{w}; 227 $self->{force_w} = $layout->{w} * $CFClient::UI::ROOT->{alloc_w} if exists $layout->{w};
227 $self->{force_h} = $layout->{h} * $CFClient::UI::ROOT->{h} if exists $layout->{h}; 228 $self->{force_h} = $layout->{h} * $CFClient::UI::ROOT->{alloc_h} if exists $layout->{h};
228 229
229 $self->{x} -= $self->{force_w} * 0.5 if exists $layout->{x}; 230 $self->{x} -= $self->{force_w} * 0.5 if exists $layout->{x};
230 $self->{y} -= $self->{force_h} * 0.5 if exists $layout->{y}; 231 $self->{y} -= $self->{force_h} * 0.5 if exists $layout->{y};
231 232
232 $self->show if $layout->{show}; 233 $self->show if $layout->{show};
355 $self->{x} = $x; 356 $self->{x} = $x;
356 $self->{y} = $y; 357 $self->{y} = $y;
357 $self->update; 358 $self->update;
358 } 359 }
359 360
360 if ($self->{w} != $w || $self->{h} != $h) { 361 if ($self->{alloc_w} != $w || $self->{alloc_h} != $h) {
361 return unless $self->{visible}; 362 return unless $self->{visible};
362 363
364 $self->{alloc_w} = $w;
365 $self->{alloc_h} = $h;
366
363 $self->{root}->{size_alloc}{$self+0} = [$self, $w, $h]; 367 $self->{root}{size_alloc}{$self+0} = $self;
364 } 368 }
365} 369}
366 370
367sub size_allocate { 371sub size_allocate {
368 # nothing to be done 372 # nothing to be done
446 my ($self, $ev, $x, $y) = @_; 450 my ($self, $ev, $x, $y) = @_;
447 451
448 $self->focus_in; 452 $self->focus_in;
449} 453}
450 454
451sub w { $_[0]{w} = $_[1] if @_ > 1; $_[0]{w} }
452sub h { $_[0]{h} = $_[1] if @_ > 1; $_[0]{h} }
453sub x { $_[0]{x} = $_[1] if @_ > 1; $_[0]{x} }
454sub y { $_[0]{y} = $_[1] if @_ > 1; $_[0]{y} }
455sub z { $_[0]{z} = $_[1] if @_ > 1; $_[0]{z} }
456
457sub find_widget { 455sub find_widget {
458 my ($self, $x, $y) = @_; 456 my ($self, $x, $y) = @_;
459 457
460 return () unless $self->{can_events}; 458 return () unless $self->{can_events};
461 459
498 496
499sub realloc { 497sub realloc {
500 my ($self) = @_; 498 my ($self) = @_;
501 499
502 if ($self->{visible}) { 500 if ($self->{visible}) {
503 return if $self->{root}{realloc}{$self}; 501 return if $self->{root}{realloc}{$self+0};
504 502
505 $self->{root}{realloc}{$self} = $self; 503 $self->{root}{realloc}{$self+0} = $self;
506 $self->{root}->update; 504 $self->{root}->update;
507 } else { 505 } else {
508 delete $self->{req_w}; 506 delete $self->{req_w};
507 delete $self->{req_h};
509 } 508 }
510} 509}
511 510
512sub update { 511sub update {
513 my ($self) = @_; 512 my ($self) = @_;
521 520
522 $self->realloc; 521 $self->realloc;
523 $self->update; 522 $self->update;
524} 523}
525 524
525# using global variables seems a bit hacky, but passing through all drawing
526# functions seems pointless.
527our ($draw_x, $draw_y, $draw_w, $draw_h); # screen rectangle being drawn
528
526sub draw { 529sub draw {
527 my ($self) = @_; 530 my ($self) = @_;
528 531
529 return unless $self->{h} && $self->{w}; 532 return unless $self->{h} && $self->{w};
533
534 # update screen rectangle
535 local $draw_x = $draw_x + $self->{x};
536 local $draw_y = $draw_y + $self->{y};
537 local $draw_w = $draw_x + $self->{w};
538 local $draw_h = $draw_y + $self->{h};
539
540 # skip widgets that are entirely outside the drawing area
541 return if ($draw_x + $self->{w} < 0) || ($draw_x >= $draw_w)
542 || ($draw_y + $self->{h} < 0) || ($draw_y >= $draw_h);
530 543
531 glPushMatrix; 544 glPushMatrix;
532 glTranslate $self->{x}, $self->{y}, 0; 545 glTranslate $self->{x}, $self->{y}, 0;
533 $self->_draw; 546 $self->_draw;
534 glPopMatrix; 547 glPopMatrix;
546 glVertex $x , $y + $self->{h}; 559 glVertex $x , $y + $self->{h};
547 glEnd; 560 glEnd;
548 glDisable GL_BLEND; 561 glDisable GL_BLEND;
549 } 562 }
550 563
551 if ($ENV{CFPLUS_DEBUG}) { 564 if ($ENV{CFPLUS_DEBUG} & 1) {
552 glPushMatrix; 565 glPushMatrix;
553 glColor 1, 1, 0, 1; 566 glColor 1, 1, 0, 1;
554 glTranslate $self->{x} + 0.375, $self->{y} + 0.375; 567 glTranslate $self->{x} + 0.375, $self->{y} + 0.375;
555 glBegin GL_LINE_LOOP; 568 glBegin GL_LINE_LOOP;
556 glVertex 0 , 0; 569 glVertex 0 , 0;
765sub size_request { 778sub size_request {
766 $_[0]{children}[0]->size_request 779 $_[0]{children}[0]->size_request
767} 780}
768 781
769sub size_allocate { 782sub size_allocate {
770 my ($self, $w, $h, $changed) = @_; 783 my ($self, $w, $h) = @_;
771 784
772 $self->{children}[0]->configure (0, 0, $w, $h); 785 $self->{children}[0]->configure (0, 0, $w, $h);
773} 786}
774 787
775############################################################################# 788#############################################################################
792 $ROOT->on_post_alloc ($self => sub { $self->render_child }); 805 $ROOT->on_post_alloc ($self => sub { $self->render_child });
793 $self->SUPER::update; 806 $self->SUPER::update;
794} 807}
795 808
796sub size_allocate { 809sub size_allocate {
797 my ($self, $w, $h, $changed) = @_; 810 my ($self, $w, $h) = @_;
798 811
799 $self->SUPER::size_allocate ($w, $h, $changed); 812 $self->SUPER::size_allocate ($w, $h);
800 $self->update 813 $self->update;
801 if $changed;
802} 814}
803 815
804sub _render { 816sub _render {
817 my ($self) = @_;
818
805 $_[0]{children}[0]->draw; 819 $self->{children}[0]->draw;
806} 820}
807 821
808sub render_child { 822sub render_child {
809 my ($self) = @_; 823 my ($self) = @_;
810 824
811 $self->{texture} = new_from_opengl CFClient::Texture $self->{w}, $self->{h}, sub { 825 $self->{texture} = new_from_opengl CFClient::Texture $self->{w}, $self->{h}, sub {
812 glClearColor 0, 0, 0, 0; 826 glClearColor 0, 0, 0, 0;
813 glClear GL_COLOR_BUFFER_BIT; 827 glClear GL_COLOR_BUFFER_BIT;
814 828
829 {
830 package CFClient::UI::Base;
831
832 ($draw_x, $draw_y, $draw_w, $draw_h) =
833 (0, 0, $self->{w}, $self->{h});
834 }
835
815 $self->_render; 836 $self->_render;
816 }; 837 };
817} 838}
818 839
819sub _draw { 840sub _draw {
820 my ($self) = @_; 841 my ($self) = @_;
821 842
822 my ($w, $h) = ($self->w, $self->h); 843 my ($w, $h) = @$self{qw(w h)};
823 844
824 my $tex = $self->{texture} 845 my $tex = $self->{texture}
825 or return; 846 or return;
826 847
827 glEnable GL_TEXTURE_2D; 848 glEnable GL_TEXTURE_2D;
850} 871}
851 872
852sub size_request { 873sub size_request {
853 my ($self) = @_; 874 my ($self) = @_;
854 875
855 my ($w, $h) = @$self{qw(child_w child_h)} = @{$self->child}{qw(req_w req_h)}; 876 my ($w, $h) = @{$self->child}{qw(req_w req_h)};
856 877
857 $w = 10 if $self->{scroll_x}; 878 $w = 10 if $self->{scroll_x};
858 $h = 10 if $self->{scroll_y}; 879 $h = 10 if $self->{scroll_y};
859 880
860 ($w, $h) 881 ($w, $h)
861} 882}
862 883
863sub size_allocate { 884sub size_allocate {
864 my ($self, $w, $h, $changed) = @_; 885 my ($self, $w, $h) = @_;
865 886
887 my $child = $self->child;
888
866 $w = $self->{child_w} if $self->{scroll_x} && $self->{child_w}; 889 $w = $child->{req_w} if $self->{scroll_x} && $child->{req_w};
867 $h = $self->{child_h} if $self->{scroll_y} && $self->{child_h}; 890 $h = $child->{req_h} if $self->{scroll_y} && $child->{req_h};
868 891
869 $self->child->configure (0, 0, $w, $h); 892 $self->child->configure (0, 0, $w, $h);
870 $self->update; 893 $self->update;
871} 894}
872 895
907 } 930 }
908} 931}
909 932
910sub _render { 933sub _render {
911 my ($self) = @_; 934 my ($self) = @_;
935
936 local $CFClient::UI::Base::draw_x = $CFClient::UI::Base::draw_x - $self->{view_x};
937 local $CFClient::UI::Base::draw_y = $CFClient::UI::Base::draw_y - $self->{view_y};
912 938
913 CFClient::OpenGL::glTranslate -$self->{view_x}, -$self->{view_y}; 939 CFClient::OpenGL::glTranslate -$self->{view_x}, -$self->{view_y};
914 940
915 $self->SUPER::_render; 941 $self->SUPER::_render;
916} 942}
956 my $child = $self->{vp}->child; 982 my $child = $self->{vp}->child;
957 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]); 983 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]);
958} 984}
959 985
960sub size_allocate { 986sub size_allocate {
961 my ($self, $w, $h, $changed) = @_; 987 my ($self, $w, $h) = @_;
962 988
963 $self->SUPER::size_allocate ($w, $h, $changed); 989 $self->SUPER::size_allocate ($w, $h);
964 990
965 my $child = $self->{vp}->child; 991 my $child = $self->{vp}->child;
966 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]); 992 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]);
967} 993}
968 994
1061 $h + $self->border * 2, 1087 $h + $self->border * 2,
1062 ) 1088 )
1063} 1089}
1064 1090
1065sub size_allocate { 1091sub size_allocate {
1066 my ($self, $w, $h, $changed) = @_; 1092 my ($self, $w, $h) = @_;
1067
1068 return unless $changed;
1069 1093
1070 $h -= List::Util::max 0, $self->border * 2; 1094 $h -= List::Util::max 0, $self->border * 2;
1071 $w -= List::Util::max 0, $self->border * 2; 1095 $w -= List::Util::max 0, $self->border * 2;
1072 1096
1073 $self->{title}->configure ($self->border, int $self->border - $::FONTSIZE * 2, $w, int $::FONTSIZE * 2) 1097 $self->{title}->configure ($self->border, int $self->border - $::FONTSIZE * 2, $w, int $::FONTSIZE * 2)
1245 (sum @$hs), 1269 (sum @$hs),
1246 ) 1270 )
1247} 1271}
1248 1272
1249sub size_allocate { 1273sub size_allocate {
1250 my ($self, $w, $h, $changed) = @_; 1274 my ($self, $w, $h) = @_;
1251 1275
1252 my ($ws, $hs) = $self->get_wh; 1276 my ($ws, $hs) = $self->get_wh;
1253 1277
1254 my $req_w = (sum @$ws) || 1; 1278 my $req_w = (sum @$ws) || 1;
1255 my $req_h = (sum @$hs) || 1; 1279 my $req_h = (sum @$hs) || 1;
1333 (List::Util::max map $_->{req_h}, @{$self->{children}}), 1357 (List::Util::max map $_->{req_h}, @{$self->{children}}),
1334 ) 1358 )
1335} 1359}
1336 1360
1337sub size_allocate { 1361sub size_allocate {
1338 my ($self, $w, $h, $changed) = @_; 1362 my ($self, $w, $h) = @_;
1339 1363
1340 my $space = $self->{vertical} ? $h : $w; 1364 my $space = $self->{vertical} ? $h : $w;
1341 my $children = $self->{children}; 1365 my $children = $self->{children};
1342 1366
1343 my @req; 1367 my @req;
1517 1541
1518 ($w, $h) 1542 ($w, $h)
1519} 1543}
1520 1544
1521sub size_allocate { 1545sub size_allocate {
1522 my ($self, $w, $h, $changed) = @_; 1546 my ($self, $w, $h) = @_;
1523 1547
1524 delete $self->{texture} 1548 delete $self->{texture}
1525 if $changed; 1549 unless $w >= $self->{req_w} && $self->{old_w} >= $self->{req_w};
1526} 1550}
1527 1551
1528sub set_fontsize { 1552sub set_fontsize {
1529 my ($self, $fontsize) = @_; 1553 my ($self, $fontsize) = @_;
1530 1554
2382 $self->{fontsize} = $fontsize; 2406 $self->{fontsize} = $fontsize;
2383 $self->reflow; 2407 $self->reflow;
2384} 2408}
2385 2409
2386sub size_allocate { 2410sub size_allocate {
2387 my ($self, $w, $h, $changed) = @_; 2411 my ($self, $w, $h) = @_;
2388 2412
2389 $self->SUPER::size_allocate ($w, $h, $changed); 2413 $self->SUPER::size_allocate ($w, $h);
2390
2391 return unless $changed;
2392 2414
2393 $self->{layout}->set_font ($self->{font}) if $self->{font}; 2415 $self->{layout}->set_font ($self->{font}) if $self->{font};
2394 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); 2416 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE);
2395 $self->{layout}->set_width ($self->{children}[0]{w}); 2417 $self->{layout}->set_width ($self->{children}[0]{w});
2396 2418
2619} 2641}
2620 2642
2621sub set_tooltip_from { 2643sub set_tooltip_from {
2622 my ($self, $widget) = @_; 2644 my ($self, $widget) = @_;
2623 2645
2646 my $tooltip = $widget->{tooltip};
2647
2648 if ($ENV{CFPLUS_DEBUG} & 2) {
2649 $tooltip .= "\n\n" . (ref $widget) . "\n"
2650 . "$widget->{x} $widget->{y} $widget->{w} $widget->{h}\n"
2651 . "req $widget->{req_w} $widget->{req_h}\n"
2652 . "visible $widget->{visible}";
2653 }
2654
2624 $self->add (new CFClient::UI::Label 2655 $self->add (new CFClient::UI::Label
2625 markup => $widget->{tooltip}, 2656 markup => $tooltip,
2626 max_w => ($widget->{tooltip_width} || 0.25) * $::WIDTH, 2657 max_w => ($widget->{tooltip_width} || 0.25) * $::WIDTH,
2627 fontsize => 0.8, 2658 fontsize => 0.8,
2628 fg => [0, 0, 0, 1], 2659 fg => [0, 0, 0, 1],
2629 ellipsise => 0, 2660 ellipsise => 0,
2630 font => ($widget->{tooltip_font} || $::FONT_PROP), 2661 font => ($widget->{tooltip_font} || $::FONT_PROP),
2638 2669
2639 ($w + 4, $h + 4) 2670 ($w + 4, $h + 4)
2640} 2671}
2641 2672
2642sub size_allocate { 2673sub size_allocate {
2643 my ($self, $w, $h, $changed) = @_; 2674 my ($self, $w, $h) = @_;
2644 2675
2645 return unless $changed;
2646
2647 $self->SUPER::size_allocate ($w - 4, $h - 4, $changed); 2676 $self->SUPER::size_allocate ($w - 4, $h - 4);
2648} 2677}
2649 2678
2650sub visibility_change { 2679sub visibility_change {
2651 my ($self, $visible) = @_; 2680 my ($self, $visible) = @_;
2652 2681
2769 2798
2770 $self->{timer}->cancel 2799 $self->{timer}->cancel
2771 if $self->{timer}; 2800 if $self->{timer};
2772 2801
2773 $self->SUPER::DESTROY; 2802 $self->SUPER::DESTROY;
2774}
2775
2776#############################################################################
2777
2778package CFClient::UI::Inventory;
2779
2780our @ISA = CFClient::UI::ScrolledWindow::;
2781
2782sub new {
2783 my $class = shift;
2784
2785 my $self = $class->SUPER::new (
2786 scrolled => (new CFClient::UI::Table col_expand => [0, 1, 0]),
2787 @_,
2788 );
2789
2790 $self
2791}
2792
2793sub set_items {
2794 my ($self, $items) = @_;
2795
2796 $self->{scrolled}->clear;
2797 return unless $items;
2798
2799 my @items = sort {
2800 ($a->{type} <=> $b->{type})
2801 or ($a->{name} cmp $b->{name})
2802 } @$items;
2803
2804 $self->{real_items} = \@items;
2805
2806 my $row = 0;
2807 for my $item (@items) {
2808 CFClient::Item::update_widgets $item;
2809
2810 $self->{scrolled}->add (0, $row, $item->{face_widget});
2811 $self->{scrolled}->add (1, $row, $item->{desc_widget});
2812 $self->{scrolled}->add (2, $row, $item->{weight_widget});
2813
2814 $row++;
2815 }
2816} 2803}
2817 2804
2818############################################################################# 2805#############################################################################
2819 2806
2820package CFClient::UI::Menu; 2807package CFClient::UI::Menu;
2997 $self->SUPER::reconfigure; 2984 $self->SUPER::reconfigure;
2998} 2985}
2999 2986
3000############################################################################# 2987#############################################################################
3001 2988
2989package CFClient::UI::Inventory;
2990
2991our @ISA = CFClient::UI::ScrolledWindow::;
2992
2993sub new {
2994 my $class = shift;
2995
2996 my $self = $class->SUPER::new (
2997 scrolled => (new CFClient::UI::Table col_expand => [0, 1, 0]),
2998 @_,
2999 );
3000
3001 $self
3002}
3003
3004sub set_items {
3005 my ($self, $items) = @_;
3006
3007 $self->{scrolled}->clear;
3008 return unless $items;
3009
3010 my @items = sort {
3011 ($a->{type} <=> $b->{type})
3012 or ($a->{name} cmp $b->{name})
3013 } @$items;
3014
3015 $self->{real_items} = \@items;
3016
3017 my $row = 0;
3018 for my $item (@items) {
3019 CFClient::Item::update_widgets $item;
3020
3021 $self->{scrolled}->add (0, $row, $item->{face_widget});
3022 $self->{scrolled}->add (1, $row, $item->{desc_widget});
3023 $self->{scrolled}->add (2, $row, $item->{weight_widget});
3024
3025 $row++;
3026 }
3027}
3028
3029#############################################################################
3030
3031package CFClient::UI::BindEditor;
3032
3033our @ISA = CFClient::UI::FancyFrame::;
3034
3035sub new {
3036 my $class = shift;
3037
3038 my $self = $class->SUPER::new (binding => [], commands => [], @_);
3039
3040 $self->add (my $vb = new CFClient::UI::VBox);
3041
3042
3043 $vb->add ($self->{rec_btn} = new CFClient::UI::Button
3044 text => "start recording",
3045 tooltip => "Start/Stops recording of actions."
3046 ."All subsequent actions after the recording started will be captured."
3047 ."The actions are displayed after the record was stopped."
3048 ."To bind the action you have to click on the 'Bind' button",
3049 on_activate => sub {
3050 unless ($self->{recording}) {
3051 $self->start;
3052 } else {
3053 $self->stop;
3054 }
3055 });
3056
3057 $vb->add (new CFClient::UI::Label text => "Actions:");
3058 $vb->add ($self->{cmdbox} = new CFClient::UI::VBox);
3059
3060 $vb->add (new CFClient::UI::Label text => "Bound to: ");
3061 $vb->add (my $hb = new CFClient::UI::HBox);
3062 $hb->add ($self->{keylbl} = new CFClient::UI::Label expand => 1);
3063 $hb->add (new CFClient::UI::Button
3064 text => "bind",
3065 tooltip => "This opens a query where you have to press the key combination to bind the recorded actions",
3066 on_activate => sub {
3067 $self->ask_for_bind;
3068 });
3069
3070 $vb->add (my $hb = new CFClient::UI::HBox);
3071 $hb->add (new CFClient::UI::Button
3072 text => "ok",
3073 expand => 1,
3074 tooltip => "This closes the binding editor and saves the binding",
3075 on_activate => sub {
3076 $self->hide;
3077 $self->commit;
3078 });
3079
3080 $hb->add (new CFClient::UI::Button
3081 text => "cancel",
3082 expand => 1,
3083 tooltip => "This closes the binding editor without saving",
3084 on_activate => sub {
3085 $self->hide;
3086 $self->{binding_cancel}->()
3087 if $self->{binding_cancel};
3088 });
3089
3090 $self->update_binding_widgets;
3091
3092 $self
3093}
3094
3095sub commit {
3096 my ($self) = @_;
3097 my ($mod, $sym, $cmds) = $self->get_binding;
3098 if ($sym != 0 && @$cmds > 0) {
3099 $::STATUSBOX->add ("Bound actions to '".CFClient::Binder::keycombo_to_name ($mod, $sym)
3100 ."'. Don't forget 'Save Config'!");
3101 $self->{binding_change}->($mod, $sym, $cmds)
3102 if $self->{binding_change};
3103 } else {
3104 $::STATUSBOX->add ("No action bound, no key or action specified!");
3105 $self->{binding_cancel}->()
3106 if $self->{binding_cancel};
3107 }
3108}
3109
3110sub start {
3111 my ($self) = @_;
3112
3113 $self->{rec_btn}->set_text ("stop recording");
3114 $self->{recording} = 1;
3115 $self->clear_command_list;
3116 $::CONN->start_record if $::CONN;
3117}
3118
3119sub stop {
3120 my ($self) = @_;
3121
3122 $self->{rec_btn}->set_text ("start recording");
3123 $self->{recording} = 0;
3124
3125 my $rec;
3126 $rec = $::CONN->stop_record if $::CONN;
3127 return unless ref $rec eq 'ARRAY';
3128 $self->set_command_list ($rec);
3129}
3130
3131# if $commit is true, the binding will be set after the user entered a key combo
3132sub ask_for_bind {
3133 my ($self, $commit) = @_;
3134
3135 CFClient::Binder::open_binding_dialog (sub {
3136 my ($mod, $sym) = @_;
3137 $self->{binding} = [$mod, $sym]; # XXX: how to stop that memleak?
3138 $self->update_binding_widgets;
3139 $self->commit if $commit;
3140 });
3141}
3142
3143# $mod and $sym are the modifiers and key symbol
3144# $cmds is a array ref of strings (the commands)
3145# $cb is the callback that is executed on OK
3146# $ccb is the callback that is executed on CANCEL and
3147# when the binding was unsuccessful on OK
3148sub set_binding {
3149 my ($self, $mod, $sym, $cmds, $cb, $ccb) = @_;
3150
3151 $self->clear_command_list;
3152 $self->{recording} = 0;
3153 $self->{rec_btn}->set_text ("start recording");
3154
3155 $self->{binding} = [$mod, $sym];
3156 $self->{commands} = $cmds;
3157
3158 $self->{binding_change} = $cb;
3159 $self->{binding_cancel} = $ccb;
3160
3161 $self->update_binding_widgets;
3162}
3163
3164# this is a shortcut method that asks for a binding
3165# and then just binds it.
3166sub do_quick_binding {
3167 my ($self, $cmds) = @_;
3168 $self->set_binding (undef, undef, $cmds, sub {
3169 $::CFG->{bindings}->{$_[0]}->{$_[1]} = $_[2];
3170 });
3171 $self->ask_for_bind (1);
3172}
3173
3174sub update_binding_widgets {
3175 my ($self) = @_;
3176 my ($mod, $sym, $cmds) = $self->get_binding;
3177 $self->{keylbl}->set_text (CFClient::Binder::keycombo_to_name ($mod, $sym));
3178 $self->set_command_list ($cmds);
3179}
3180
3181sub get_binding {
3182 my ($self) = @_;
3183 return (
3184 $self->{binding}->[0],
3185 $self->{binding}->[1],
3186 [ grep { defined $_ } @{$self->{commands}} ]
3187 );
3188}
3189
3190sub clear_command_list {
3191 my ($self) = @_;
3192 $self->{cmdbox}->clear ();
3193}
3194
3195sub set_command_list {
3196 my ($self, $cmds) = @_;
3197
3198 $self->{cmdbox}->clear ();
3199 $self->{commands} = $cmds;
3200
3201 my $idx = 0;
3202
3203 for (@$cmds) {
3204 $self->{cmdbox}->add (my $hb = new CFClient::UI::HBox);
3205
3206 my $i = $idx;
3207 $hb->add (new CFClient::UI::Label text => $_);
3208 $hb->add (new CFClient::UI::Button
3209 text => "delete",
3210 tooltip => "Deletes the action from the record",
3211 on_activate => sub {
3212 $self->{cmdbox}->remove ($hb);
3213 $cmds->[$i] = undef;
3214 });
3215
3216
3217 $idx++
3218 }
3219}
3220
3221#############################################################################
3222
3223package CFClient::UI::SpellList;
3224
3225our @ISA = CFClient::UI::FancyFrame::;
3226
3227sub new {
3228 my $class = shift;
3229
3230 my $self = $class->SUPER::new (binding => [], commands => [], @_);
3231
3232 $self->add (new CFClient::UI::ScrolledWindow
3233 scrolled => $self->{spellbox} = new CFClient::UI::Table);
3234
3235 $self;
3236}
3237
3238# XXX: Do sorting? Argl...
3239sub add_spell {
3240 my ($self, $spell) = @_;
3241 $self->{spells}->{$spell->{name}} = $spell;
3242
3243 $self->{spellbox}->add (0, $self->{tbl_idx}, new CFClient::UI::Face
3244 face => $spell->{face},
3245 can_hover => 1,
3246 can_events => 1,
3247 tooltip => $spell->{message});
3248
3249 $self->{spellbox}->add (1, $self->{tbl_idx}, new CFClient::UI::Label
3250 text => $spell->{name},
3251 can_hover => 1,
3252 can_events => 1,
3253 tooltip => $spell->{message},
3254 expand => 1);
3255
3256 $self->{spellbox}->add (2, $self->{tbl_idx}, new CFClient::UI::Label
3257 text => (sprintf "lvl: %2d sp: %2d dmg: %2d",
3258 $spell->{level}, ($spell->{mana} || $spell->{grace}), $spell->{damage}),
3259 expand => 1);
3260
3261 $self->{spellbox}->add (3, $self->{tbl_idx}++, new CFClient::UI::Button
3262 text => "bind to key",
3263 on_activate => sub { $::BIND_EDITOR->do_quick_binding (["cast $spell->{name}"]) });
3264}
3265
3266sub rebuild_spell_list {
3267 my ($self) = @_;
3268 $self->{tbl_idx} = 0;
3269 $self->add_spell ($_) for values %{$self->{spells}};
3270}
3271
3272sub remove_spell {
3273 my ($self, $spell) = @_;
3274 delete $self->{spells}->{$spell->{name}};
3275 $self->rebuild_spell_list;
3276}
3277
3278#############################################################################
3279
3002package CFClient::UI::Root; 3280package CFClient::UI::Root;
3003 3281
3004our @ISA = CFClient::UI::Container::; 3282our @ISA = CFClient::UI::Container::;
3005 3283
3006use CFClient::OpenGL; 3284use CFClient::OpenGL;
3016 Scalar::Util::weaken ($self->{root} = $self); 3294 Scalar::Util::weaken ($self->{root} = $self);
3017 3295
3018 $self 3296 $self
3019} 3297}
3020 3298
3021sub configure {
3022 my ($self, $x, $y, $w, $h) = @_;
3023
3024 $self->{w} = $w;
3025 $self->{h} = $h;
3026}
3027
3028sub reconfigure {
3029 my ($self) = @_;
3030
3031 $self->SUPER::reconfigure;
3032
3033 $self->size_allocate ($self->{w}, $self->{h}, 1)
3034 if $self->{w};
3035}
3036
3037sub size_request { 3299sub size_request {
3038 my ($self) = @_; 3300 my ($self) = @_;
3039 3301
3040 ($self->{w}, $self->{h}) 3302 ($self->{w}, $self->{h})
3041} 3303}
3053 3315
3054 int $coord + 0.5 3316 int $coord + 0.5
3055} 3317}
3056 3318
3057sub size_allocate { 3319sub size_allocate {
3058 my ($self, $w, $h, $changed) = @_; 3320 my ($self, $w, $h) = @_;
3059 3321
3060 for my $child ($self->children) { 3322 for my $child ($self->children) {
3061 my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)}; 3323 my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)};
3062 3324
3063 $X = $child->{force_x} if exists $child->{force_x}; 3325 $X = $child->{force_x} if exists $child->{force_x};
3131 $_->() 3393 $_->()
3132 for values %{delete $self->{refresh_hook}}; 3394 for values %{delete $self->{refresh_hook}};
3133 } 3395 }
3134 3396
3135 if ($self->{realloc}) { 3397 if ($self->{realloc}) {
3398 my %queue;
3136 my @queue; 3399 my @queue;
3400 my $widget;
3137 3401
3402 outer:
3138 while () { 3403 while () {
3139 if ($self->{realloc}) { 3404 if (my $realloc = delete $self->{realloc}) {
3140 #TODO use array-of-depth approach 3405 for $widget (values %$realloc) {
3406 $widget->{visible} or next; # do not resize invisible widgets
3141 3407
3142 @queue = sort { $a->{visible} <=> $b->{visible} } 3408 $queue{$widget+0}++ and next; # duplicates are common
3143 @queue, values %{delete $self->{realloc}}; 3409
3410 push @{ $queue[$widget->{visible}] }, $widget;
3411 }
3144 } 3412 }
3145 3413
3414 while () {
3415 @queue or last outer;
3416
3146 my $widget = pop @queue || last; 3417 $widget = pop @{ $queue[-1] || [] }
3418 and last;
3419
3420 pop @queue;
3421 }
3147 3422
3148 $widget->{visible} or last; # do not resize invisible widgets 3423 delete $queue{$widget+0};
3149 3424
3150 my ($w, $h) = $widget->size_request; 3425 my ($w, $h) = $widget->size_request;
3151 3426
3152 $w = List::Util::max $widget->{min_w}, $w + $widget->{padding_x} * 2; 3427 $w = List::Util::max $widget->{min_w}, $w + $widget->{padding_x} * 2;
3153 $h = List::Util::max $widget->{min_h}, $h + $widget->{padding_y} * 2; 3428 $h = List::Util::max $widget->{min_h}, $h + $widget->{padding_y} * 2;
3154 3429
3155 $w = $widget->{force_w} if exists $widget->{force_w}; 3430 $w = $widget->{force_w} if exists $widget->{force_w};
3156 $h = $widget->{force_h} if exists $widget->{force_h}; 3431 $h = $widget->{force_h} if exists $widget->{force_h};
3157 3432
3433 if ($widget->{req_w} != $w || $widget->{req_h} != $h
3434 || delete $widget->{force_realloc}) {
3158 $widget->{req_w} = $w; 3435 $widget->{req_w} = $w;
3159 $widget->{req_h} = $h; 3436 $widget->{req_h} = $h;
3160 3437
3161 $self->{size_alloc}{$widget} = [$widget, undef, undef]; 3438 $self->{size_alloc}{$widget+0} = $widget;
3162 3439
3163 push @queue, $widget->{parent} 3440 if (my $parent = $widget->{parent}) {
3164 if ($self->{w} != $w || $self->{h} != $h) && $widget->{parent}; 3441 $self->{realloc}{$parent+0} = $parent
3442 unless $queue{$parent+0};
3443
3444 $parent->{force_size_alloc} = 1;
3445 $self->{size_alloc}{$parent+0} = $parent;
3446 }
3447 }
3448
3449 delete $self->{realloc}{$widget+0};
3165 } 3450 }
3166 } 3451 }
3167 3452
3168 while (my $size_alloc = delete $self->{size_alloc}) { 3453 while (my $size_alloc = delete $self->{size_alloc}) {
3169 my @queue = sort $b->[0]{visible} <=> $a->[0]{visible}, 3454 my @queue = sort { $b->{visible} <=> $a->{visible} }
3170 values %$size_alloc; 3455 values %$size_alloc;
3171 3456
3172 while () { 3457 while () {
3173 my ($widget, $w, $h) = @{ pop @queue or last }; 3458 my $widget = pop @queue || last;
3174 3459
3175 $w = $widget->{w} || $widget->{req_w} unless defined $w; 3460 my ($w, $h) = @$widget{qw(alloc_w alloc_h)};
3176 $h = $widget->{h} || $widget->{req_h} unless defined $h;
3177 3461
3178 $w = 0 if $w < 0; 3462 $w = 0 if $w < 0;
3179 $h = 0 if $h < 0; 3463 $h = 0 if $h < 0;
3180 3464
3181 $w = int $w + 0.5; 3465 $w = int $w + 0.5;
3182 $h = int $h + 0.5; 3466 $h = int $h + 0.5;
3183 3467
3184 my $changed = $widget->{w} != $w || $widget->{h} != $h; 3468 if ($widget->{w} != $w || $widget->{h} != $h || delete $widget->{force_size_alloc}) {
3469 $widget->{old_w} = $widget->{w};
3470 $widget->{old_h} = $widget->{h};
3185 3471
3186 $widget->{w} = $w; 3472 $widget->{w} = $w;
3187 $widget->{h} = $h; 3473 $widget->{h} = $h;
3188 3474
3189 $widget->emit (size_allocate => $w, $h, $changed); 3475 $widget->emit (size_allocate => $w, $h);
3476 }
3190 } 3477 }
3191 } 3478 }
3192 3479
3193 while ($self->{post_alloc_hook}) { 3480 while ($self->{post_alloc_hook}) {
3194 $_->() 3481 $_->()
3195 for values %{delete $self->{post_alloc_hook}}; 3482 for values %{delete $self->{post_alloc_hook}};
3196 } 3483 }
3484
3197 3485
3198 glViewport 0, 0, $::WIDTH, $::HEIGHT; 3486 glViewport 0, 0, $::WIDTH, $::HEIGHT;
3199 glClearColor +($::CFG->{fow_intensity}) x 3, 1; 3487 glClearColor +($::CFG->{fow_intensity}) x 3, 1;
3200 glClear GL_COLOR_BUFFER_BIT; 3488 glClear GL_COLOR_BUFFER_BIT;
3201 3489
3203 glLoadIdentity; 3491 glLoadIdentity;
3204 glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000, 10000; 3492 glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000, 10000;
3205 glMatrixMode GL_MODELVIEW; 3493 glMatrixMode GL_MODELVIEW;
3206 glLoadIdentity; 3494 glLoadIdentity;
3207 3495
3496 {
3497 package CFClient::UI::Base;
3498
3499 ($draw_x, $draw_y, $draw_w, $draw_h) =
3500 (0, 0, $self->{w}, $self->{h});
3501 }
3502
3208 $self->_draw; 3503 $self->_draw;
3209} 3504}
3210 3505
3211############################################################################# 3506#############################################################################
3212 3507

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines