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.271 by root, Fri Jun 2 22:13:47 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
435 439
436 $::MAPWIDGET->focus_in #d# focus mapwidget if no other widget has focus 440 $::MAPWIDGET->focus_in #d# focus mapwidget if no other widget has focus
437 unless $FOCUS; 441 unless $FOCUS;
438} 442}
439 443
440sub mouse_motion { } 444sub mouse_motion { 0 }
441sub button_up { } 445sub button_up { 0 }
442sub key_down { } 446sub key_down { 0 }
443sub key_up { } 447sub key_up { 0 }
444 448
445sub button_down { 449sub button_down {
446 my ($self, $ev, $x, $y) = @_; 450 my ($self, $ev, $x, $y) = @_;
447 451
448 $self->focus_in; 452 $self->focus_in;
449}
450 453
451sub w { $_[0]{w} = $_[1] if @_ > 1; $_[0]{w} } 454 0
452sub h { $_[0]{h} = $_[1] if @_ > 1; $_[0]{h} } 455}
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 456
457sub find_widget { 457sub find_widget {
458 my ($self, $x, $y) = @_; 458 my ($self, $x, $y) = @_;
459 459
460 return () unless $self->{can_events}; 460 return () unless $self->{can_events};
498 498
499sub realloc { 499sub realloc {
500 my ($self) = @_; 500 my ($self) = @_;
501 501
502 if ($self->{visible}) { 502 if ($self->{visible}) {
503 return if $self->{root}{realloc}{$self}; 503 return if $self->{root}{realloc}{$self+0};
504 504
505 $self->{root}{realloc}{$self} = $self; 505 $self->{root}{realloc}{$self+0} = $self;
506 $self->{root}->update; 506 $self->{root}->update;
507 } else { 507 } else {
508 delete $self->{req_w}; 508 delete $self->{req_w};
509 delete $self->{req_h};
509 } 510 }
510} 511}
511 512
512sub update { 513sub update {
513 my ($self) = @_; 514 my ($self) = @_;
521 522
522 $self->realloc; 523 $self->realloc;
523 $self->update; 524 $self->update;
524} 525}
525 526
527# using global variables seems a bit hacky, but passing through all drawing
528# functions seems pointless.
529our ($draw_x, $draw_y, $draw_w, $draw_h); # screen rectangle being drawn
530
526sub draw { 531sub draw {
527 my ($self) = @_; 532 my ($self) = @_;
528 533
529 return unless $self->{h} && $self->{w}; 534 return unless $self->{h} && $self->{w};
535
536 # update screen rectangle
537 local $draw_x = $draw_x + $self->{x};
538 local $draw_y = $draw_y + $self->{y};
539 local $draw_w = $draw_x + $self->{w};
540 local $draw_h = $draw_y + $self->{h};
541
542 # skip widgets that are entirely outside the drawing area
543 return if ($draw_x + $self->{w} < 0) || ($draw_x >= $draw_w)
544 || ($draw_y + $self->{h} < 0) || ($draw_y >= $draw_h);
530 545
531 glPushMatrix; 546 glPushMatrix;
532 glTranslate $self->{x}, $self->{y}, 0; 547 glTranslate $self->{x}, $self->{y}, 0;
533 $self->_draw; 548 $self->_draw;
534 glPopMatrix; 549 glPopMatrix;
546 glVertex $x , $y + $self->{h}; 561 glVertex $x , $y + $self->{h};
547 glEnd; 562 glEnd;
548 glDisable GL_BLEND; 563 glDisable GL_BLEND;
549 } 564 }
550 565
551 if ($ENV{CFPLUS_DEBUG}) { 566 if ($ENV{CFPLUS_DEBUG} & 1) {
552 glPushMatrix; 567 glPushMatrix;
553 glColor 1, 1, 0, 1; 568 glColor 1, 1, 0, 1;
554 glTranslate $self->{x} + 0.375, $self->{y} + 0.375; 569 glTranslate $self->{x} + 0.375, $self->{y} + 0.375;
555 glBegin GL_LINE_LOOP; 570 glBegin GL_LINE_LOOP;
556 glVertex 0 , 0; 571 glVertex 0 , 0;
765sub size_request { 780sub size_request {
766 $_[0]{children}[0]->size_request 781 $_[0]{children}[0]->size_request
767} 782}
768 783
769sub size_allocate { 784sub size_allocate {
770 my ($self, $w, $h, $changed) = @_; 785 my ($self, $w, $h) = @_;
771 786
772 $self->{children}[0]->configure (0, 0, $w, $h); 787 $self->{children}[0]->configure (0, 0, $w, $h);
773} 788}
774 789
775############################################################################# 790#############################################################################
792 $ROOT->on_post_alloc ($self => sub { $self->render_child }); 807 $ROOT->on_post_alloc ($self => sub { $self->render_child });
793 $self->SUPER::update; 808 $self->SUPER::update;
794} 809}
795 810
796sub size_allocate { 811sub size_allocate {
797 my ($self, $w, $h, $changed) = @_; 812 my ($self, $w, $h) = @_;
798 813
799 $self->SUPER::size_allocate ($w, $h, $changed); 814 $self->SUPER::size_allocate ($w, $h);
800 $self->update 815 $self->update;
801 if $changed;
802} 816}
803 817
804sub _render { 818sub _render {
819 my ($self) = @_;
820
805 $_[0]{children}[0]->draw; 821 $self->{children}[0]->draw;
806} 822}
807 823
808sub render_child { 824sub render_child {
809 my ($self) = @_; 825 my ($self) = @_;
810 826
811 $self->{texture} = new_from_opengl CFClient::Texture $self->{w}, $self->{h}, sub { 827 $self->{texture} = new_from_opengl CFClient::Texture $self->{w}, $self->{h}, sub {
812 glClearColor 0, 0, 0, 0; 828 glClearColor 0, 0, 0, 0;
813 glClear GL_COLOR_BUFFER_BIT; 829 glClear GL_COLOR_BUFFER_BIT;
814 830
831 {
832 package CFClient::UI::Base;
833
834 ($draw_x, $draw_y, $draw_w, $draw_h) =
835 (0, 0, $self->{w}, $self->{h});
836 }
837
815 $self->_render; 838 $self->_render;
816 }; 839 };
817} 840}
818 841
819sub _draw { 842sub _draw {
820 my ($self) = @_; 843 my ($self) = @_;
821 844
822 my ($w, $h) = ($self->w, $self->h); 845 my ($w, $h) = @$self{qw(w h)};
823 846
824 my $tex = $self->{texture} 847 my $tex = $self->{texture}
825 or return; 848 or return;
826 849
827 glEnable GL_TEXTURE_2D; 850 glEnable GL_TEXTURE_2D;
850} 873}
851 874
852sub size_request { 875sub size_request {
853 my ($self) = @_; 876 my ($self) = @_;
854 877
855 my ($w, $h) = @$self{qw(child_w child_h)} = @{$self->child}{qw(req_w req_h)}; 878 my ($w, $h) = @{$self->child}{qw(req_w req_h)};
856 879
857 $w = 10 if $self->{scroll_x}; 880 $w = 10 if $self->{scroll_x};
858 $h = 10 if $self->{scroll_y}; 881 $h = 10 if $self->{scroll_y};
859 882
860 ($w, $h) 883 ($w, $h)
861} 884}
862 885
863sub size_allocate { 886sub size_allocate {
864 my ($self, $w, $h, $changed) = @_; 887 my ($self, $w, $h) = @_;
865 888
889 my $child = $self->child;
890
866 $w = $self->{child_w} if $self->{scroll_x} && $self->{child_w}; 891 $w = $child->{req_w} if $self->{scroll_x} && $child->{req_w};
867 $h = $self->{child_h} if $self->{scroll_y} && $self->{child_h}; 892 $h = $child->{req_h} if $self->{scroll_y} && $child->{req_h};
868 893
869 $self->child->configure (0, 0, $w, $h); 894 $self->child->configure (0, 0, $w, $h);
870 $self->update; 895 $self->update;
871} 896}
872 897
907 } 932 }
908} 933}
909 934
910sub _render { 935sub _render {
911 my ($self) = @_; 936 my ($self) = @_;
937
938 local $CFClient::UI::Base::draw_x = $CFClient::UI::Base::draw_x - $self->{view_x};
939 local $CFClient::UI::Base::draw_y = $CFClient::UI::Base::draw_y - $self->{view_y};
912 940
913 CFClient::OpenGL::glTranslate -$self->{view_x}, -$self->{view_y}; 941 CFClient::OpenGL::glTranslate -$self->{view_x}, -$self->{view_y};
914 942
915 $self->SUPER::_render; 943 $self->SUPER::_render;
916} 944}
956 my $child = $self->{vp}->child; 984 my $child = $self->{vp}->child;
957 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]); 985 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]);
958} 986}
959 987
960sub size_allocate { 988sub size_allocate {
961 my ($self, $w, $h, $changed) = @_; 989 my ($self, $w, $h) = @_;
962 990
963 $self->SUPER::size_allocate ($w, $h, $changed); 991 $self->SUPER::size_allocate ($w, $h);
964 992
965 my $child = $self->{vp}->child; 993 my $child = $self->{vp}->child;
966 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]); 994 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]);
967} 995}
968 996
1024my @border = 1052my @border =
1025 map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 } 1053 map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 }
1026 qw(d1_border_top.png d1_border_right.png d1_border_left.png d1_border_bottom.png); 1054 qw(d1_border_top.png d1_border_right.png d1_border_left.png d1_border_bottom.png);
1027 1055
1028sub new { 1056sub new {
1029 my $class = shift; 1057 my ($class, %arg) = @_;
1058
1059 my $title = delete $arg{title};
1030 1060
1031 my $self = $class->SUPER::new ( 1061 my $self = $class->SUPER::new (
1032 bg => [1, 1, 1, 1], 1062 bg => [1, 1, 1, 1],
1033 border_bg => [1, 1, 1, 1], 1063 border_bg => [1, 1, 1, 1],
1034 border => 0.6, 1064 border => 0.6,
1035 can_events => 1, 1065 can_events => 1,
1036 min_w => 16, 1066 min_w => 16,
1037 min_h => 16, 1067 min_h => 16,
1038 @_ 1068 %arg,
1039 ); 1069 );
1040 1070
1041 $self->{title} &&= new CFClient::UI::Label 1071 $self->{title} = new CFClient::UI::Label
1042 align => 0, 1072 align => 0,
1043 valign => 1, 1073 valign => 1,
1044 text => $self->{title}, 1074 text => $title,
1045 fontsize => $self->{border}; 1075 fontsize => $self->{border}
1076 if defined $title;
1046 1077
1047 $self 1078 $self
1079}
1080
1081sub add {
1082 my ($self, @widgets) = @_;
1083
1084 $self->SUPER::add (@widgets);
1085 $self->CFClient::UI::Container::add ($self->{title}) if $self->{title};
1048} 1086}
1049 1087
1050sub border { 1088sub border {
1051 int $_[0]{border} * $::FONTSIZE 1089 int $_[0]{border} * $::FONTSIZE
1052} 1090}
1053 1091
1054sub size_request { 1092sub size_request {
1055 my ($self) = @_; 1093 my ($self) = @_;
1094
1095 $self->{title}->size_request
1096 if $self->{title};
1056 1097
1057 my ($w, $h) = $self->SUPER::size_request; 1098 my ($w, $h) = $self->SUPER::size_request;
1058 1099
1059 ( 1100 (
1060 $w + $self->border * 2, 1101 $w + $self->border * 2,
1061 $h + $self->border * 2, 1102 $h + $self->border * 2,
1062 ) 1103 )
1063} 1104}
1064 1105
1065sub size_allocate { 1106sub size_allocate {
1066 my ($self, $w, $h, $changed) = @_; 1107 my ($self, $w, $h) = @_;
1067 1108
1068 return unless $changed; 1109 if ($self->{title}) {
1110 $self->{title}{w} = $w;
1111 $self->{title}{h} = $h;
1112 $self->{title}->size_allocate ($w, $h);
1113 }
1069 1114
1115 my $border = $self->border;
1116
1070 $h -= List::Util::max 0, $self->border * 2; 1117 $h -= List::Util::max 0, $border * 2;
1071 $w -= List::Util::max 0, $self->border * 2; 1118 $w -= List::Util::max 0, $border * 2;
1072 1119
1073 $self->{title}->configure ($self->border, int $self->border - $::FONTSIZE * 2, $w, int $::FONTSIZE * 2)
1074 if $self->{title};
1075
1076 $self->child->configure ($self->border, $self->border, $w, $h); 1120 $self->child->configure ($border, $border, $w, $h);
1077} 1121}
1078 1122
1079sub button_down { 1123sub button_down {
1080 my ($self, $ev, $x, $y) = @_; 1124 my ($self, $ev, $x, $y) = @_;
1081 1125
1115 1159
1116 ($x, $y) = ($ev->{x}, $ev->{y}); 1160 ($x, $y) = ($ev->{x}, $ev->{y});
1117 1161
1118 $self->move_abs ($bx + $x - $ox, $by + $y - $oy); 1162 $self->move_abs ($bx + $x - $ox, $by + $y - $oy);
1119 }; 1163 };
1164 } else {
1165 return 0;
1166 }
1167
1120 } 1168 1
1121} 1169}
1122 1170
1123sub button_up { 1171sub button_up {
1124 my ($self, $ev, $x, $y) = @_; 1172 my ($self, $ev, $x, $y) = @_;
1125 1173
1126 delete $self->{motion}; 1174 !!delete $self->{motion}
1127} 1175}
1128 1176
1129sub mouse_motion { 1177sub mouse_motion {
1130 my ($self, $ev, $x, $y) = @_; 1178 my ($self, $ev, $x, $y) = @_;
1131 1179
1132 $self->{motion}->($ev, $x, $y) if $self->{motion}; 1180 $self->{motion}->($ev, $x, $y) if $self->{motion};
1181
1182 !!$self->{motion}
1133} 1183}
1134 1184
1135sub _draw { 1185sub _draw {
1136 my ($self) = @_; 1186 my ($self) = @_;
1137 1187
1188 my $child = $self->{children}[0];
1189
1138 my ($w, $h ) = ($self->{w}, $self->{h}); 1190 my ($w, $h ) = ($self->{w}, $self->{h});
1139 my ($cw, $ch) = ($self->child->{w}, $self->child->{h}); 1191 my ($cw, $ch) = ($child->{w}, $child->{h});
1140 1192
1141 glEnable GL_TEXTURE_2D; 1193 glEnable GL_TEXTURE_2D;
1142 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE; 1194 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE;
1143 1195
1144 my $border = $self->border; 1196 my $border = $self->border;
1159 $bg->draw_quad_alpha ($border, $border, $cw, $ch); 1211 $bg->draw_quad_alpha ($border, $border, $cw, $ch);
1160 } 1212 }
1161 1213
1162 glDisable GL_TEXTURE_2D; 1214 glDisable GL_TEXTURE_2D;
1163 1215
1164 $self->{title}->draw if $self->{title};
1165
1166 $self->child->draw; 1216 $child->draw;
1217
1218 if ($self->{title}) {
1219 glTranslate 0, $border - $self->{h};
1220 $self->{title}->_draw;
1221 }
1167} 1222}
1168 1223
1169############################################################################# 1224#############################################################################
1170 1225
1171package CFClient::UI::Table; 1226package CFClient::UI::Table;
1245 (sum @$hs), 1300 (sum @$hs),
1246 ) 1301 )
1247} 1302}
1248 1303
1249sub size_allocate { 1304sub size_allocate {
1250 my ($self, $w, $h, $changed) = @_; 1305 my ($self, $w, $h) = @_;
1251 1306
1252 my ($ws, $hs) = $self->get_wh; 1307 my ($ws, $hs) = $self->get_wh;
1253 1308
1254 my $req_w = (sum @$ws) || 1; 1309 my $req_w = (sum @$ws) || 1;
1255 my $req_h = (sum @$hs) || 1; 1310 my $req_h = (sum @$hs) || 1;
1333 (List::Util::max map $_->{req_h}, @{$self->{children}}), 1388 (List::Util::max map $_->{req_h}, @{$self->{children}}),
1334 ) 1389 )
1335} 1390}
1336 1391
1337sub size_allocate { 1392sub size_allocate {
1338 my ($self, $w, $h, $changed) = @_; 1393 my ($self, $w, $h) = @_;
1339 1394
1340 my $space = $self->{vertical} ? $h : $w; 1395 my $space = $self->{vertical} ? $h : $w;
1341 my $children = $self->{children}; 1396 my $children = $self->{children};
1342 1397
1343 my @req; 1398 my @req;
1517 1572
1518 ($w, $h) 1573 ($w, $h)
1519} 1574}
1520 1575
1521sub size_allocate { 1576sub size_allocate {
1522 my ($self, $w, $h, $changed) = @_; 1577 my ($self, $w, $h) = @_;
1578
1579 delete $self->{ox};
1523 1580
1524 delete $self->{texture} 1581 delete $self->{texture}
1525 if $changed; 1582 unless $w >= $self->{req_w} && $self->{old_w} >= $self->{req_w};
1526} 1583}
1527 1584
1528sub set_fontsize { 1585sub set_fontsize {
1529 my ($self, $fontsize) = @_; 1586 my ($self, $fontsize) = @_;
1530 1587
1545 $self->{layout}->set_width ($self->{w}); 1602 $self->{layout}->set_width ($self->{w});
1546 $self->{layout}->set_ellipsise ($self->{ellipsise}); 1603 $self->{layout}->set_ellipsise ($self->{ellipsise});
1547 $self->{layout}->set_single_paragraph_mode ($self->{ellipsise}); 1604 $self->{layout}->set_single_paragraph_mode ($self->{ellipsise});
1548 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); 1605 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE);
1549 1606
1550 my $tex = new_from_layout CFClient::Texture $self->{layout}; 1607 new_from_layout CFClient::Texture $self->{layout}
1608 };
1551 1609
1610 unless (exists $self->{ox}) {
1552 $self->{ox} = int ($self->{align} < 0 ? $self->{padding_x} 1611 $self->{ox} = int ($self->{align} < 0 ? $self->{padding_x}
1553 : $self->{align} > 0 ? $self->{w} - $tex->{w} - $self->{padding_x} 1612 : $self->{align} > 0 ? $self->{w} - $tex->{w} - $self->{padding_x}
1554 : ($self->{w} - $tex->{w}) * 0.5); 1613 : ($self->{w} - $tex->{w}) * 0.5);
1555 1614
1556 $self->{oy} = int ($self->{valign} < 0 ? $self->{padding_y} 1615 $self->{oy} = int ($self->{valign} < 0 ? $self->{padding_y}
1557 : $self->{valign} > 0 ? $self->{h} - $tex->{h} - $self->{padding_y} 1616 : $self->{valign} > 0 ? $self->{h} - $tex->{h} - $self->{padding_y}
1558 : ($self->{h} - $tex->{h}) * 0.5); 1617 : ($self->{h} - $tex->{h}) * 0.5);
1559
1560 $tex
1561 }; 1618 };
1562 1619
1563 glEnable GL_TEXTURE_2D; 1620 glEnable GL_TEXTURE_2D;
1564 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; 1621 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE;
1565 1622
1660 $self->{cursor} = length $text; 1717 $self->{cursor} = length $text;
1661 } elsif ($uni == 27) { 1718 } elsif ($uni == 27) {
1662 $self->_emit ('escape'); 1719 $self->_emit ('escape');
1663 } elsif ($uni) { 1720 } elsif ($uni) {
1664 substr $text, $self->{cursor}++, 0, chr $uni; 1721 substr $text, $self->{cursor}++, 0, chr $uni;
1722 } else {
1723 return 0;
1665 } 1724 }
1666 1725
1667 $self->_set_text ($text); 1726 $self->_set_text ($text);
1668 1727
1669 $self->realloc; 1728 $self->realloc;
1729
1730 1
1670} 1731}
1671 1732
1672sub focus_in { 1733sub focus_in {
1673 my ($self) = @_; 1734 my ($self) = @_;
1674 1735
1689 utf8::encode $text; 1750 utf8::encode $text;
1690 $self->{cursor} = length substr $text, 0, $idx; 1751 $self->{cursor} = length substr $text, 0, $idx;
1691 1752
1692 $self->_set_text ($self->{text}); 1753 $self->_set_text ($self->{text});
1693 $self->update; 1754 $self->update;
1755
1756 1
1694} 1757}
1695 1758
1696sub mouse_motion { 1759sub mouse_motion {
1697 my ($self, $ev, $x, $y) = @_; 1760 my ($self, $ev, $x, $y) = @_;
1698# printf "M %d,%d %d,%d\n", $ev->motion_x, $ev->motion_y, $x, $y;#d# 1761# printf "M %d,%d %d,%d\n", $ev->motion_x, $ev->motion_y, $x, $y;#d#
1762
1763 0
1699} 1764}
1700 1765
1701sub _draw { 1766sub _draw {
1702 my ($self) = @_; 1767 my ($self) = @_;
1703 1768
1780 } else { 1845 } else {
1781 $self->set_text ($self->{history_saveback}); 1846 $self->set_text ($self->{history_saveback});
1782 } 1847 }
1783 1848
1784 } else { 1849 } else {
1785 $self->SUPER::key_down ($ev); 1850 return $self->SUPER::key_down ($ev)
1851 }
1852
1786 } 1853 1
1787
1788} 1854}
1789 1855
1790############################################################################# 1856#############################################################################
1791 1857
1792package CFClient::UI::Button; 1858package CFClient::UI::Button;
1821 my ($self, $ev, $x, $y) = @_; 1887 my ($self, $ev, $x, $y) = @_;
1822 1888
1823 $self->emit ("activate") 1889 $self->emit ("activate")
1824 if $x >= 0 && $x < $self->{w} 1890 if $x >= 0 && $x < $self->{w}
1825 && $y >= 0 && $y < $self->{h}; 1891 && $y >= 0 && $y < $self->{h};
1892
1893 1
1826} 1894}
1827 1895
1828sub _draw { 1896sub _draw {
1829 my ($self) = @_; 1897 my ($self) = @_;
1830 1898
1884 1952
1885 if ($x >= $self->{padding_x} && $x < $self->{w} - $self->{padding_x} 1953 if ($x >= $self->{padding_x} && $x < $self->{w} - $self->{padding_x}
1886 && $y >= $self->{padding_y} && $y < $self->{h} - $self->{padding_y}) { 1954 && $y >= $self->{padding_y} && $y < $self->{h} - $self->{padding_y}) {
1887 $self->{state} = !$self->{state}; 1955 $self->{state} = !$self->{state};
1888 $self->_emit (changed => $self->{state}); 1956 $self->_emit (changed => $self->{state});
1957 } else {
1958 return 0
1959 }
1960
1889 } 1961 1
1890} 1962}
1891 1963
1892sub _draw { 1964sub _draw {
1893 my ($self) = @_; 1965 my ($self) = @_;
1894 1966
2232 2304
2233 $self->SUPER::button_down ($ev, $x, $y); 2305 $self->SUPER::button_down ($ev, $x, $y);
2234 2306
2235 $self->{click} = [$self->{range}[0], $self->{vertical} ? $y : $x]; 2307 $self->{click} = [$self->{range}[0], $self->{vertical} ? $y : $x];
2236 2308
2237 $self->mouse_motion ($ev, $x, $y); 2309 $self->mouse_motion ($ev, $x, $y)
2238} 2310}
2239 2311
2240sub mouse_motion { 2312sub mouse_motion {
2241 my ($self, $ev, $x, $y) = @_; 2313 my ($self, $ev, $x, $y) = @_;
2242 2314
2246 my (undef, $lo, $hi, $page) = @{$self->{range}}; 2318 my (undef, $lo, $hi, $page) = @{$self->{range}};
2247 2319
2248 $x = ($x - $self->{click}[1]) / ($w * $self->{scale}); 2320 $x = ($x - $self->{click}[1]) / ($w * $self->{scale});
2249 2321
2250 $self->set_value ($self->{click}[0] + $x * ($hi - $page - $lo)); 2322 $self->set_value ($self->{click}[0] + $x * ($hi - $page - $lo));
2323 } else {
2324 return 0;
2325 }
2326
2251 } 2327 1
2252} 2328}
2253 2329
2254sub update { 2330sub update {
2255 my ($self) = @_; 2331 my ($self) = @_;
2256 2332
2382 $self->{fontsize} = $fontsize; 2458 $self->{fontsize} = $fontsize;
2383 $self->reflow; 2459 $self->reflow;
2384} 2460}
2385 2461
2386sub size_allocate { 2462sub size_allocate {
2387 my ($self, $w, $h, $changed) = @_; 2463 my ($self, $w, $h) = @_;
2388 2464
2389 $self->SUPER::size_allocate ($w, $h, $changed); 2465 $self->SUPER::size_allocate ($w, $h);
2390
2391 return unless $changed;
2392 2466
2393 $self->{layout}->set_font ($self->{font}) if $self->{font}; 2467 $self->{layout}->set_font ($self->{font}) if $self->{font};
2394 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); 2468 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE);
2395 $self->{layout}->set_width ($self->{children}[0]{w}); 2469 $self->{layout}->set_width ($self->{children}[0]{w});
2396 2470
2619} 2693}
2620 2694
2621sub set_tooltip_from { 2695sub set_tooltip_from {
2622 my ($self, $widget) = @_; 2696 my ($self, $widget) = @_;
2623 2697
2698 my $tooltip = $widget->{tooltip};
2699
2700 if ($ENV{CFPLUS_DEBUG} & 2) {
2701 $tooltip .= "\n\n" . (ref $widget) . "\n"
2702 . "$widget->{x} $widget->{y} $widget->{w} $widget->{h}\n"
2703 . "req $widget->{req_w} $widget->{req_h}\n"
2704 . "visible $widget->{visible}";
2705 }
2706
2624 $self->add (new CFClient::UI::Label 2707 $self->add (new CFClient::UI::Label
2625 markup => $widget->{tooltip}, 2708 markup => $tooltip,
2626 max_w => ($widget->{tooltip_width} || 0.25) * $::WIDTH, 2709 max_w => ($widget->{tooltip_width} || 0.25) * $::WIDTH,
2627 fontsize => 0.8, 2710 fontsize => 0.8,
2628 fg => [0, 0, 0, 1], 2711 fg => [0, 0, 0, 1],
2629 ellipsise => 0, 2712 ellipsise => 0,
2630 font => ($widget->{tooltip_font} || $::FONT_PROP), 2713 font => ($widget->{tooltip_font} || $::FONT_PROP),
2638 2721
2639 ($w + 4, $h + 4) 2722 ($w + 4, $h + 4)
2640} 2723}
2641 2724
2642sub size_allocate { 2725sub size_allocate {
2643 my ($self, $w, $h, $changed) = @_; 2726 my ($self, $w, $h) = @_;
2644 2727
2645 return unless $changed;
2646
2647 $self->SUPER::size_allocate ($w - 4, $h - 4, $changed); 2728 $self->SUPER::size_allocate ($w - 4, $h - 4);
2648} 2729}
2649 2730
2650sub visibility_change { 2731sub visibility_change {
2651 my ($self, $visible) = @_; 2732 my ($self, $visible) = @_;
2652 2733
2773 $self->SUPER::DESTROY; 2854 $self->SUPER::DESTROY;
2774} 2855}
2775 2856
2776############################################################################# 2857#############################################################################
2777 2858
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}
2817
2818#############################################################################
2819
2820package CFClient::UI::Menu; 2859package CFClient::UI::Menu;
2821 2860
2822our @ISA = CFClient::UI::FancyFrame::; 2861our @ISA = CFClient::UI::FancyFrame::;
2823 2862
2824use CFClient::OpenGL; 2863use CFClient::OpenGL;
2871 my ($self, $ev, $x, $y) = @_; 2910 my ($self, $ev, $x, $y) = @_;
2872 2911
2873 # TODO: should use vbox->find_widget or so 2912 # TODO: should use vbox->find_widget or so
2874 $HOVER = $ROOT->find_widget ($ev->{x}, $ev->{y}); 2913 $HOVER = $ROOT->find_widget ($ev->{x}, $ev->{y});
2875 $self->{hover} = $self->{item}{$HOVER}; 2914 $self->{hover} = $self->{item}{$HOVER};
2915
2916 0
2876} 2917}
2877 2918
2878sub button_up { 2919sub button_up {
2879 my ($self, $ev, $x, $y) = @_; 2920 my ($self, $ev, $x, $y) = @_;
2880 2921
2882 undef $GRAB; 2923 undef $GRAB;
2883 $self->hide; 2924 $self->hide;
2884 2925
2885 $self->_emit ("popdown"); 2926 $self->_emit ("popdown");
2886 $self->{hover}[1]->() if $self->{hover}; 2927 $self->{hover}[1]->() if $self->{hover};
2928 } else {
2929 return 0
2930 }
2931
2887 } 2932 1
2888} 2933}
2889 2934
2890############################################################################# 2935#############################################################################
2891 2936
2892package CFClient::UI::Statusbox; 2937package CFClient::UI::Statusbox;
2997 $self->SUPER::reconfigure; 3042 $self->SUPER::reconfigure;
2998} 3043}
2999 3044
3000############################################################################# 3045#############################################################################
3001 3046
3047package CFClient::UI::Inventory;
3048
3049our @ISA = CFClient::UI::ScrolledWindow::;
3050
3051sub new {
3052 my $class = shift;
3053
3054 my $self = $class->SUPER::new (
3055 scrolled => (new CFClient::UI::Table col_expand => [0, 1, 0]),
3056 @_,
3057 );
3058
3059 $self
3060}
3061
3062sub set_items {
3063 my ($self, $items) = @_;
3064
3065 $self->{scrolled}->clear;
3066 return unless $items;
3067
3068 my @items = sort {
3069 ($a->{type} <=> $b->{type})
3070 or ($a->{name} cmp $b->{name})
3071 } @$items;
3072
3073 $self->{real_items} = \@items;
3074
3075 my $row = 0;
3076 for my $item (@items) {
3077 CFClient::Item::update_widgets $item;
3078
3079 $self->{scrolled}->add (0, $row, $item->{face_widget});
3080 $self->{scrolled}->add (1, $row, $item->{desc_widget});
3081 $self->{scrolled}->add (2, $row, $item->{weight_widget});
3082
3083 $row++;
3084 }
3085}
3086
3087#############################################################################
3088
3089package CFClient::UI::BindEditor;
3090
3091our @ISA = CFClient::UI::FancyFrame::;
3092
3093sub new {
3094 my $class = shift;
3095
3096 my $self = $class->SUPER::new (binding => [], commands => [], @_);
3097
3098 $self->add (my $vb = new CFClient::UI::VBox);
3099
3100
3101 $vb->add ($self->{rec_btn} = new CFClient::UI::Button
3102 text => "start recording",
3103 tooltip => "Start/Stops recording of actions."
3104 ."All subsequent actions after the recording started will be captured."
3105 ."The actions are displayed after the record was stopped."
3106 ."To bind the action you have to click on the 'Bind' button",
3107 on_activate => sub {
3108 unless ($self->{recording}) {
3109 $self->start;
3110 } else {
3111 $self->stop;
3112 }
3113 });
3114
3115 $vb->add (new CFClient::UI::Label text => "Actions:");
3116 $vb->add ($self->{cmdbox} = new CFClient::UI::VBox);
3117
3118 $vb->add (new CFClient::UI::Label text => "Bound to: ");
3119 $vb->add (my $hb = new CFClient::UI::HBox);
3120 $hb->add ($self->{keylbl} = new CFClient::UI::Label expand => 1);
3121 $hb->add (new CFClient::UI::Button
3122 text => "bind",
3123 tooltip => "This opens a query where you have to press the key combination to bind the recorded actions",
3124 on_activate => sub {
3125 $self->ask_for_bind;
3126 });
3127
3128 $vb->add (my $hb = new CFClient::UI::HBox);
3129 $hb->add (new CFClient::UI::Button
3130 text => "ok",
3131 expand => 1,
3132 tooltip => "This closes the binding editor and saves the binding",
3133 on_activate => sub {
3134 $self->hide;
3135 $self->commit;
3136 });
3137
3138 $hb->add (new CFClient::UI::Button
3139 text => "cancel",
3140 expand => 1,
3141 tooltip => "This closes the binding editor without saving",
3142 on_activate => sub {
3143 $self->hide;
3144 $self->{binding_cancel}->()
3145 if $self->{binding_cancel};
3146 });
3147
3148 $self->update_binding_widgets;
3149
3150 $self
3151}
3152
3153sub commit {
3154 my ($self) = @_;
3155 my ($mod, $sym, $cmds) = $self->get_binding;
3156 if ($sym != 0 && @$cmds > 0) {
3157 $::STATUSBOX->add ("Bound actions to '".CFClient::Binder::keycombo_to_name ($mod, $sym)
3158 ."'. Don't forget 'Save Config'!");
3159 $self->{binding_change}->($mod, $sym, $cmds)
3160 if $self->{binding_change};
3161 } else {
3162 $::STATUSBOX->add ("No action bound, no key or action specified!");
3163 $self->{binding_cancel}->()
3164 if $self->{binding_cancel};
3165 }
3166}
3167
3168sub start {
3169 my ($self) = @_;
3170
3171 $self->{rec_btn}->set_text ("stop recording");
3172 $self->{recording} = 1;
3173 $self->clear_command_list;
3174 $::CONN->start_record if $::CONN;
3175}
3176
3177sub stop {
3178 my ($self) = @_;
3179
3180 $self->{rec_btn}->set_text ("start recording");
3181 $self->{recording} = 0;
3182
3183 my $rec;
3184 $rec = $::CONN->stop_record if $::CONN;
3185 return unless ref $rec eq 'ARRAY';
3186 $self->set_command_list ($rec);
3187}
3188
3189
3190sub ask_for_bind_and_commit {
3191 my ($self) = @_;
3192 $self->ask_for_bind (1);
3193}
3194
3195sub ask_for_bind {
3196 my ($self, $commit) = @_;
3197
3198 CFClient::Binder::open_binding_dialog (sub {
3199 my ($mod, $sym) = @_;
3200 $self->{binding} = [$mod, $sym]; # XXX: how to stop that memleak?
3201 $self->update_binding_widgets;
3202 $self->commit if $commit;
3203 });
3204}
3205
3206# $mod and $sym are the modifiers and key symbol
3207# $cmds is a array ref of strings (the commands)
3208# $cb is the callback that is executed on OK
3209# $ccb is the callback that is executed on CANCEL and
3210# when the binding was unsuccessful on OK
3211sub set_binding {
3212 my ($self, $mod, $sym, $cmds, $cb, $ccb) = @_;
3213
3214 $self->clear_command_list;
3215 $self->{recording} = 0;
3216 $self->{rec_btn}->set_text ("start recording");
3217
3218 $self->{binding} = [$mod, $sym];
3219 $self->{commands} = $cmds;
3220
3221 $self->{binding_change} = $cb;
3222 $self->{binding_cancel} = $ccb;
3223
3224 $self->update_binding_widgets;
3225}
3226
3227# this is a shortcut method that asks for a binding
3228# and then just binds it.
3229sub do_quick_binding {
3230 my ($self, $cmds) = @_;
3231 $self->set_binding (undef, undef, $cmds, sub {
3232 $::CFG->{bindings}->{$_[0]}->{$_[1]} = $_[2];
3233 });
3234 $self->ask_for_bind (1);
3235}
3236
3237sub update_binding_widgets {
3238 my ($self) = @_;
3239 my ($mod, $sym, $cmds) = $self->get_binding;
3240 $self->{keylbl}->set_text (CFClient::Binder::keycombo_to_name ($mod, $sym));
3241 $self->set_command_list ($cmds);
3242}
3243
3244sub get_binding {
3245 my ($self) = @_;
3246 return (
3247 $self->{binding}->[0],
3248 $self->{binding}->[1],
3249 [ grep { defined $_ } @{$self->{commands}} ]
3250 );
3251}
3252
3253sub clear_command_list {
3254 my ($self) = @_;
3255 $self->{cmdbox}->clear ();
3256}
3257
3258sub set_command_list {
3259 my ($self, $cmds) = @_;
3260
3261 $self->{cmdbox}->clear ();
3262 $self->{commands} = $cmds;
3263
3264 my $idx = 0;
3265
3266 for (@$cmds) {
3267 $self->{cmdbox}->add (my $hb = new CFClient::UI::HBox);
3268
3269 my $i = $idx;
3270 $hb->add (new CFClient::UI::Label text => $_);
3271 $hb->add (new CFClient::UI::Button
3272 text => "delete",
3273 tooltip => "Deletes the action from the record",
3274 on_activate => sub {
3275 $self->{cmdbox}->remove ($hb);
3276 $cmds->[$i] = undef;
3277 });
3278
3279
3280 $idx++
3281 }
3282}
3283
3284#############################################################################
3285
3286package CFClient::UI::SpellList;
3287
3288our @ISA = CFClient::UI::FancyFrame::;
3289
3290sub new {
3291 my $class = shift;
3292
3293 my $self = $class->SUPER::new (binding => [], commands => [], @_);
3294
3295 $self->add (new CFClient::UI::ScrolledWindow
3296 scrolled => $self->{spellbox} = new CFClient::UI::Table);
3297
3298 $self;
3299}
3300
3301# XXX: Do sorting? Argl...
3302sub add_spell {
3303 my ($self, $spell) = @_;
3304 $self->{spells}->{$spell->{name}} = $spell;
3305
3306 $self->{spellbox}->add (0, $self->{tbl_idx}, new CFClient::UI::Face
3307 face => $spell->{face},
3308 can_hover => 1,
3309 can_events => 1,
3310 tooltip => $spell->{message});
3311
3312 $self->{spellbox}->add (1, $self->{tbl_idx}, new CFClient::UI::Label
3313 text => $spell->{name},
3314 can_hover => 1,
3315 can_events => 1,
3316 tooltip => $spell->{message},
3317 expand => 1);
3318
3319 $self->{spellbox}->add (2, $self->{tbl_idx}, new CFClient::UI::Label
3320 text => (sprintf "lvl: %2d sp: %2d dmg: %2d",
3321 $spell->{level}, ($spell->{mana} || $spell->{grace}), $spell->{damage}),
3322 expand => 1);
3323
3324 $self->{spellbox}->add (3, $self->{tbl_idx}++, new CFClient::UI::Button
3325 text => "bind to key",
3326 on_activate => sub { $::BIND_EDITOR->do_quick_binding (["cast $spell->{name}"]) });
3327}
3328
3329sub rebuild_spell_list {
3330 my ($self) = @_;
3331 $self->{tbl_idx} = 0;
3332 $self->add_spell ($_) for values %{$self->{spells}};
3333}
3334
3335sub remove_spell {
3336 my ($self, $spell) = @_;
3337 delete $self->{spells}->{$spell->{name}};
3338 $self->rebuild_spell_list;
3339}
3340
3341#############################################################################
3342
3002package CFClient::UI::Root; 3343package CFClient::UI::Root;
3003 3344
3004our @ISA = CFClient::UI::Container::; 3345our @ISA = CFClient::UI::Container::;
3005 3346
3006use CFClient::OpenGL; 3347use CFClient::OpenGL;
3016 Scalar::Util::weaken ($self->{root} = $self); 3357 Scalar::Util::weaken ($self->{root} = $self);
3017 3358
3018 $self 3359 $self
3019} 3360}
3020 3361
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 { 3362sub size_request {
3038 my ($self) = @_; 3363 my ($self) = @_;
3039 3364
3040 ($self->{w}, $self->{h}) 3365 ($self->{w}, $self->{h})
3041} 3366}
3053 3378
3054 int $coord + 0.5 3379 int $coord + 0.5
3055} 3380}
3056 3381
3057sub size_allocate { 3382sub size_allocate {
3058 my ($self, $w, $h, $changed) = @_; 3383 my ($self, $w, $h) = @_;
3059 3384
3060 for my $child ($self->children) { 3385 for my $child ($self->children) {
3061 my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)}; 3386 my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)};
3062 3387
3063 $X = $child->{force_x} if exists $child->{force_x}; 3388 $X = $child->{force_x} if exists $child->{force_x};
3131 $_->() 3456 $_->()
3132 for values %{delete $self->{refresh_hook}}; 3457 for values %{delete $self->{refresh_hook}};
3133 } 3458 }
3134 3459
3135 if ($self->{realloc}) { 3460 if ($self->{realloc}) {
3461 my %queue;
3136 my @queue; 3462 my @queue;
3463 my $widget;
3137 3464
3465 outer:
3138 while () { 3466 while () {
3139 if ($self->{realloc}) { 3467 if (my $realloc = delete $self->{realloc}) {
3140 #TODO use array-of-depth approach 3468 for $widget (values %$realloc) {
3469 $widget->{visible} or next; # do not resize invisible widgets
3141 3470
3142 @queue = sort { $a->{visible} <=> $b->{visible} } 3471 $queue{$widget+0}++ and next; # duplicates are common
3143 @queue, values %{delete $self->{realloc}}; 3472
3473 push @{ $queue[$widget->{visible}] }, $widget;
3474 }
3144 } 3475 }
3145 3476
3477 while () {
3478 @queue or last outer;
3479
3146 my $widget = pop @queue || last; 3480 $widget = pop @{ $queue[-1] || [] }
3481 and last;
3482
3483 pop @queue;
3484 }
3147 3485
3148 $widget->{visible} or last; # do not resize invisible widgets 3486 delete $queue{$widget+0};
3149 3487
3150 my ($w, $h) = $widget->size_request; 3488 my ($w, $h) = $widget->size_request;
3151 3489
3152 $w = List::Util::max $widget->{min_w}, $w + $widget->{padding_x} * 2; 3490 $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; 3491 $h = List::Util::max $widget->{min_h}, $h + $widget->{padding_y} * 2;
3154 3492
3155 $w = $widget->{force_w} if exists $widget->{force_w}; 3493 $w = $widget->{force_w} if exists $widget->{force_w};
3156 $h = $widget->{force_h} if exists $widget->{force_h}; 3494 $h = $widget->{force_h} if exists $widget->{force_h};
3157 3495
3496 if ($widget->{req_w} != $w || $widget->{req_h} != $h
3497 || delete $widget->{force_realloc}) {
3158 $widget->{req_w} = $w; 3498 $widget->{req_w} = $w;
3159 $widget->{req_h} = $h; 3499 $widget->{req_h} = $h;
3160 3500
3161 $self->{size_alloc}{$widget} = [$widget, undef, undef]; 3501 $self->{size_alloc}{$widget+0} = $widget;
3162 3502
3163 push @queue, $widget->{parent} 3503 if (my $parent = $widget->{parent}) {
3164 if ($self->{w} != $w || $self->{h} != $h) && $widget->{parent}; 3504 $self->{realloc}{$parent+0} = $parent
3505 unless $queue{$parent+0};
3506
3507 $parent->{force_size_alloc} = 1;
3508 $self->{size_alloc}{$parent+0} = $parent;
3509 }
3510 }
3511
3512 delete $self->{realloc}{$widget+0};
3165 } 3513 }
3166 } 3514 }
3167 3515
3168 while (my $size_alloc = delete $self->{size_alloc}) { 3516 while (my $size_alloc = delete $self->{size_alloc}) {
3169 my @queue = sort $b->[0]{visible} <=> $a->[0]{visible}, 3517 my @queue = sort { $b->{visible} <=> $a->{visible} }
3170 values %$size_alloc; 3518 values %$size_alloc;
3171 3519
3172 while () { 3520 while () {
3173 my ($widget, $w, $h) = @{ pop @queue or last }; 3521 my $widget = pop @queue || last;
3174 3522
3175 $w = $widget->{w} || $widget->{req_w} unless defined $w; 3523 my ($w, $h) = @$widget{qw(alloc_w alloc_h)};
3176 $h = $widget->{h} || $widget->{req_h} unless defined $h;
3177 3524
3178 $w = 0 if $w < 0; 3525 $w = 0 if $w < 0;
3179 $h = 0 if $h < 0; 3526 $h = 0 if $h < 0;
3180 3527
3181 $w = int $w + 0.5; 3528 $w = int $w + 0.5;
3182 $h = int $h + 0.5; 3529 $h = int $h + 0.5;
3183 3530
3184 my $changed = $widget->{w} != $w || $widget->{h} != $h; 3531 if ($widget->{w} != $w || $widget->{h} != $h || delete $widget->{force_size_alloc}) {
3532 $widget->{old_w} = $widget->{w};
3533 $widget->{old_h} = $widget->{h};
3185 3534
3186 $widget->{w} = $w; 3535 $widget->{w} = $w;
3187 $widget->{h} = $h; 3536 $widget->{h} = $h;
3188 3537
3189 $widget->emit (size_allocate => $w, $h, $changed); 3538 $widget->emit (size_allocate => $w, $h);
3539 }
3190 } 3540 }
3191 } 3541 }
3192 3542
3193 while ($self->{post_alloc_hook}) { 3543 while ($self->{post_alloc_hook}) {
3194 $_->() 3544 $_->()
3195 for values %{delete $self->{post_alloc_hook}}; 3545 for values %{delete $self->{post_alloc_hook}};
3196 } 3546 }
3547
3197 3548
3198 glViewport 0, 0, $::WIDTH, $::HEIGHT; 3549 glViewport 0, 0, $::WIDTH, $::HEIGHT;
3199 glClearColor +($::CFG->{fow_intensity}) x 3, 1; 3550 glClearColor +($::CFG->{fow_intensity}) x 3, 1;
3200 glClear GL_COLOR_BUFFER_BIT; 3551 glClear GL_COLOR_BUFFER_BIT;
3201 3552
3203 glLoadIdentity; 3554 glLoadIdentity;
3204 glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000, 10000; 3555 glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000, 10000;
3205 glMatrixMode GL_MODELVIEW; 3556 glMatrixMode GL_MODELVIEW;
3206 glLoadIdentity; 3557 glLoadIdentity;
3207 3558
3559 {
3560 package CFClient::UI::Base;
3561
3562 ($draw_x, $draw_y, $draw_w, $draw_h) =
3563 (0, 0, $self->{w}, $self->{h});
3564 }
3565
3208 $self->_draw; 3566 $self->_draw;
3209} 3567}
3210 3568
3211############################################################################# 3569#############################################################################
3212 3570

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines