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.259 by root, Tue May 30 07:13:09 2006 UTC vs.
Revision 1.269 by root, Fri Jun 2 06:22:55 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;
449 my ($self, $ev, $x, $y) = @_; 450 my ($self, $ev, $x, $y) = @_;
450 451
451 $self->focus_in; 452 $self->focus_in;
452} 453}
453 454
454sub w { $_[0]{w} = $_[1] if @_ > 1; $_[0]{w} }
455sub h { $_[0]{h} = $_[1] if @_ > 1; $_[0]{h} }
456sub x { $_[0]{x} = $_[1] if @_ > 1; $_[0]{x} }
457sub y { $_[0]{y} = $_[1] if @_ > 1; $_[0]{y} }
458sub z { $_[0]{z} = $_[1] if @_ > 1; $_[0]{z} }
459
460sub find_widget { 455sub find_widget {
461 my ($self, $x, $y) = @_; 456 my ($self, $x, $y) = @_;
462 457
463 return () unless $self->{can_events}; 458 return () unless $self->{can_events};
464 459
525 520
526 $self->realloc; 521 $self->realloc;
527 $self->update; 522 $self->update;
528} 523}
529 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
530sub draw { 529sub draw {
531 my ($self) = @_; 530 my ($self) = @_;
532 531
533 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);
534 543
535 glPushMatrix; 544 glPushMatrix;
536 glTranslate $self->{x}, $self->{y}, 0; 545 glTranslate $self->{x}, $self->{y}, 0;
537 $self->_draw; 546 $self->_draw;
538 glPopMatrix; 547 glPopMatrix;
803 $self->SUPER::size_allocate ($w, $h); 812 $self->SUPER::size_allocate ($w, $h);
804 $self->update; 813 $self->update;
805} 814}
806 815
807sub _render { 816sub _render {
817 my ($self) = @_;
818
808 $_[0]{children}[0]->draw; 819 $self->{children}[0]->draw;
809} 820}
810 821
811sub render_child { 822sub render_child {
812 my ($self) = @_; 823 my ($self) = @_;
813 824
814 $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 {
815 glClearColor 0, 0, 0, 0; 826 glClearColor 0, 0, 0, 0;
816 glClear GL_COLOR_BUFFER_BIT; 827 glClear GL_COLOR_BUFFER_BIT;
817 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
818 $self->_render; 836 $self->_render;
819 }; 837 };
820} 838}
821 839
822sub _draw { 840sub _draw {
823 my ($self) = @_; 841 my ($self) = @_;
824 842
825 my ($w, $h) = ($self->w, $self->h); 843 my ($w, $h) = @$self{qw(w h)};
826 844
827 my $tex = $self->{texture} 845 my $tex = $self->{texture}
828 or return; 846 or return;
829 847
830 glEnable GL_TEXTURE_2D; 848 glEnable GL_TEXTURE_2D;
912 } 930 }
913} 931}
914 932
915sub _render { 933sub _render {
916 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};
917 938
918 CFClient::OpenGL::glTranslate -$self->{view_x}, -$self->{view_y}; 939 CFClient::OpenGL::glTranslate -$self->{view_x}, -$self->{view_y};
919 940
920 $self->SUPER::_render; 941 $self->SUPER::_render;
921} 942}
1029my @border = 1050my @border =
1030 map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 } 1051 map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 }
1031 qw(d1_border_top.png d1_border_right.png d1_border_left.png d1_border_bottom.png); 1052 qw(d1_border_top.png d1_border_right.png d1_border_left.png d1_border_bottom.png);
1032 1053
1033sub new { 1054sub new {
1034 my $class = shift; 1055 my ($class, %arg) = @_;
1056
1057 my $title = delete $arg{title};
1035 1058
1036 my $self = $class->SUPER::new ( 1059 my $self = $class->SUPER::new (
1037 bg => [1, 1, 1, 1], 1060 bg => [1, 1, 1, 1],
1038 border_bg => [1, 1, 1, 1], 1061 border_bg => [1, 1, 1, 1],
1039 border => 0.6, 1062 border => 0.6,
1040 can_events => 1, 1063 can_events => 1,
1041 min_w => 16, 1064 min_w => 16,
1042 min_h => 16, 1065 min_h => 16,
1043 @_ 1066 %arg,
1044 ); 1067 );
1045 1068
1046 $self->{title} &&= new CFClient::UI::Label 1069 $self->{title} = new CFClient::UI::Label
1047 align => 0, 1070 align => 0,
1048 valign => 1, 1071 valign => 1,
1049 text => $self->{title}, 1072 text => $title,
1050 fontsize => $self->{border}; 1073 fontsize => $self->{border}
1074 if defined $title;
1051 1075
1052 $self 1076 $self
1077}
1078
1079sub add {
1080 my ($self, @widgets) = @_;
1081
1082 $self->SUPER::add (@widgets);
1083 $self->CFClient::UI::Container::add ($self->{title}) if $self->{title};
1053} 1084}
1054 1085
1055sub border { 1086sub border {
1056 int $_[0]{border} * $::FONTSIZE 1087 int $_[0]{border} * $::FONTSIZE
1057} 1088}
1058 1089
1059sub size_request { 1090sub size_request {
1060 my ($self) = @_; 1091 my ($self) = @_;
1092
1093 $self->{title}->size_request
1094 if $self->{title};
1061 1095
1062 my ($w, $h) = $self->SUPER::size_request; 1096 my ($w, $h) = $self->SUPER::size_request;
1063 1097
1064 ( 1098 (
1065 $w + $self->border * 2, 1099 $w + $self->border * 2,
1068} 1102}
1069 1103
1070sub size_allocate { 1104sub size_allocate {
1071 my ($self, $w, $h) = @_; 1105 my ($self, $w, $h) = @_;
1072 1106
1107 if ($self->{title}) {
1108 $self->{title}{w} = $w;
1109 $self->{title}{h} = $h;
1110 $self->{title}->size_allocate ($w, $h);
1111 }
1112
1113 my $border = $self->border;
1114
1073 $h -= List::Util::max 0, $self->border * 2; 1115 $h -= List::Util::max 0, $border * 2;
1074 $w -= List::Util::max 0, $self->border * 2; 1116 $w -= List::Util::max 0, $border * 2;
1075 1117
1076 $self->{title}->configure ($self->border, int $self->border - $::FONTSIZE * 2, $w, int $::FONTSIZE * 2)
1077 if $self->{title};
1078
1079 $self->child->configure ($self->border, $self->border, $w, $h); 1118 $self->child->configure ($border, $border, $w, $h);
1080} 1119}
1081 1120
1082sub button_down { 1121sub button_down {
1083 my ($self, $ev, $x, $y) = @_; 1122 my ($self, $ev, $x, $y) = @_;
1084 1123
1136} 1175}
1137 1176
1138sub _draw { 1177sub _draw {
1139 my ($self) = @_; 1178 my ($self) = @_;
1140 1179
1180 my $child = $self->{children}[0];
1181
1141 my ($w, $h ) = ($self->{w}, $self->{h}); 1182 my ($w, $h ) = ($self->{w}, $self->{h});
1142 my ($cw, $ch) = ($self->child->{w}, $self->child->{h}); 1183 my ($cw, $ch) = ($child->{w}, $child->{h});
1143 1184
1144 glEnable GL_TEXTURE_2D; 1185 glEnable GL_TEXTURE_2D;
1145 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE; 1186 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE;
1146 1187
1147 my $border = $self->border; 1188 my $border = $self->border;
1162 $bg->draw_quad_alpha ($border, $border, $cw, $ch); 1203 $bg->draw_quad_alpha ($border, $border, $cw, $ch);
1163 } 1204 }
1164 1205
1165 glDisable GL_TEXTURE_2D; 1206 glDisable GL_TEXTURE_2D;
1166 1207
1167 $self->{title}->draw if $self->{title};
1168
1169 $self->child->draw; 1208 $child->draw;
1209
1210 if ($self->{title}) {
1211 glTranslate 0, $border - $self->{h};
1212 $self->{title}->_draw;
1213 }
1170} 1214}
1171 1215
1172############################################################################# 1216#############################################################################
1173 1217
1174package CFClient::UI::Table; 1218package CFClient::UI::Table;
1522} 1566}
1523 1567
1524sub size_allocate { 1568sub size_allocate {
1525 my ($self, $w, $h) = @_; 1569 my ($self, $w, $h) = @_;
1526 1570
1571 delete $self->{ox};
1572
1527 delete $self->{texture}; 1573 delete $self->{texture}
1574 unless $w >= $self->{req_w} && $self->{old_w} >= $self->{req_w};
1528} 1575}
1529 1576
1530sub set_fontsize { 1577sub set_fontsize {
1531 my ($self, $fontsize) = @_; 1578 my ($self, $fontsize) = @_;
1532 1579
1547 $self->{layout}->set_width ($self->{w}); 1594 $self->{layout}->set_width ($self->{w});
1548 $self->{layout}->set_ellipsise ($self->{ellipsise}); 1595 $self->{layout}->set_ellipsise ($self->{ellipsise});
1549 $self->{layout}->set_single_paragraph_mode ($self->{ellipsise}); 1596 $self->{layout}->set_single_paragraph_mode ($self->{ellipsise});
1550 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); 1597 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE);
1551 1598
1552 my $tex = new_from_layout CFClient::Texture $self->{layout}; 1599 new_from_layout CFClient::Texture $self->{layout}
1600 };
1553 1601
1602 unless (exists $self->{ox}) {
1554 $self->{ox} = int ($self->{align} < 0 ? $self->{padding_x} 1603 $self->{ox} = int ($self->{align} < 0 ? $self->{padding_x}
1555 : $self->{align} > 0 ? $self->{w} - $tex->{w} - $self->{padding_x} 1604 : $self->{align} > 0 ? $self->{w} - $tex->{w} - $self->{padding_x}
1556 : ($self->{w} - $tex->{w}) * 0.5); 1605 : ($self->{w} - $tex->{w}) * 0.5);
1557 1606
1558 $self->{oy} = int ($self->{valign} < 0 ? $self->{padding_y} 1607 $self->{oy} = int ($self->{valign} < 0 ? $self->{padding_y}
1559 : $self->{valign} > 0 ? $self->{h} - $tex->{h} - $self->{padding_y} 1608 : $self->{valign} > 0 ? $self->{h} - $tex->{h} - $self->{padding_y}
1560 : ($self->{h} - $tex->{h}) * 0.5); 1609 : ($self->{h} - $tex->{h}) * 0.5);
1561
1562 $tex
1563 }; 1610 };
1564 1611
1565 glEnable GL_TEXTURE_2D; 1612 glEnable GL_TEXTURE_2D;
1566 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE; 1613 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE;
1567 1614
2776 2823
2777 $self->{timer}->cancel 2824 $self->{timer}->cancel
2778 if $self->{timer}; 2825 if $self->{timer};
2779 2826
2780 $self->SUPER::DESTROY; 2827 $self->SUPER::DESTROY;
2781}
2782
2783#############################################################################
2784
2785package CFClient::UI::Inventory;
2786
2787our @ISA = CFClient::UI::ScrolledWindow::;
2788
2789sub new {
2790 my $class = shift;
2791
2792 my $self = $class->SUPER::new (
2793 scrolled => (new CFClient::UI::Table col_expand => [0, 1, 0]),
2794 @_,
2795 );
2796
2797 $self
2798}
2799
2800sub set_items {
2801 my ($self, $items) = @_;
2802
2803 $self->{scrolled}->clear;
2804 return unless $items;
2805
2806 my @items = sort {
2807 ($a->{type} <=> $b->{type})
2808 or ($a->{name} cmp $b->{name})
2809 } @$items;
2810
2811 $self->{real_items} = \@items;
2812
2813 my $row = 0;
2814 for my $item (@items) {
2815 CFClient::Item::update_widgets $item;
2816
2817 $self->{scrolled}->add (0, $row, $item->{face_widget});
2818 $self->{scrolled}->add (1, $row, $item->{desc_widget});
2819 $self->{scrolled}->add (2, $row, $item->{weight_widget});
2820
2821 $row++;
2822 }
2823} 2828}
2824 2829
2825############################################################################# 2830#############################################################################
2826 2831
2827package CFClient::UI::Menu; 2832package CFClient::UI::Menu;
3004 $self->SUPER::reconfigure; 3009 $self->SUPER::reconfigure;
3005} 3010}
3006 3011
3007############################################################################# 3012#############################################################################
3008 3013
3014package CFClient::UI::Inventory;
3015
3016our @ISA = CFClient::UI::ScrolledWindow::;
3017
3018sub new {
3019 my $class = shift;
3020
3021 my $self = $class->SUPER::new (
3022 scrolled => (new CFClient::UI::Table col_expand => [0, 1, 0]),
3023 @_,
3024 );
3025
3026 $self
3027}
3028
3029sub set_items {
3030 my ($self, $items) = @_;
3031
3032 $self->{scrolled}->clear;
3033 return unless $items;
3034
3035 my @items = sort {
3036 ($a->{type} <=> $b->{type})
3037 or ($a->{name} cmp $b->{name})
3038 } @$items;
3039
3040 $self->{real_items} = \@items;
3041
3042 my $row = 0;
3043 for my $item (@items) {
3044 CFClient::Item::update_widgets $item;
3045
3046 $self->{scrolled}->add (0, $row, $item->{face_widget});
3047 $self->{scrolled}->add (1, $row, $item->{desc_widget});
3048 $self->{scrolled}->add (2, $row, $item->{weight_widget});
3049
3050 $row++;
3051 }
3052}
3053
3054#############################################################################
3055
3056package CFClient::UI::BindEditor;
3057
3058our @ISA = CFClient::UI::FancyFrame::;
3059
3060sub new {
3061 my $class = shift;
3062
3063 my $self = $class->SUPER::new (binding => [], commands => [], @_);
3064
3065 $self->add (my $vb = new CFClient::UI::VBox);
3066
3067
3068 $vb->add ($self->{rec_btn} = new CFClient::UI::Button
3069 text => "start recording",
3070 tooltip => "Start/Stops recording of actions."
3071 ."All subsequent actions after the recording started will be captured."
3072 ."The actions are displayed after the record was stopped."
3073 ."To bind the action you have to click on the 'Bind' button",
3074 on_activate => sub {
3075 unless ($self->{recording}) {
3076 $self->start;
3077 } else {
3078 $self->stop;
3079 }
3080 });
3081
3082 $vb->add (new CFClient::UI::Label text => "Actions:");
3083 $vb->add ($self->{cmdbox} = new CFClient::UI::VBox);
3084
3085 $vb->add (new CFClient::UI::Label text => "Bound to: ");
3086 $vb->add (my $hb = new CFClient::UI::HBox);
3087 $hb->add ($self->{keylbl} = new CFClient::UI::Label expand => 1);
3088 $hb->add (new CFClient::UI::Button
3089 text => "bind",
3090 tooltip => "This opens a query where you have to press the key combination to bind the recorded actions",
3091 on_activate => sub {
3092 $self->ask_for_bind;
3093 });
3094
3095 $vb->add (my $hb = new CFClient::UI::HBox);
3096 $hb->add (new CFClient::UI::Button
3097 text => "ok",
3098 expand => 1,
3099 tooltip => "This closes the binding editor and saves the binding",
3100 on_activate => sub {
3101 $self->hide;
3102 $self->commit;
3103 });
3104
3105 $hb->add (new CFClient::UI::Button
3106 text => "cancel",
3107 expand => 1,
3108 tooltip => "This closes the binding editor without saving",
3109 on_activate => sub {
3110 $self->hide;
3111 $self->{binding_cancel}->()
3112 if $self->{binding_cancel};
3113 });
3114
3115 $self->update_binding_widgets;
3116
3117 $self
3118}
3119
3120sub commit {
3121 my ($self) = @_;
3122 my ($mod, $sym, $cmds) = $self->get_binding;
3123 if ($sym != 0 && @$cmds > 0) {
3124 $::STATUSBOX->add ("Bound actions to '".CFClient::Binder::keycombo_to_name ($mod, $sym)
3125 ."'. Don't forget 'Save Config'!");
3126 $self->{binding_change}->($mod, $sym, $cmds)
3127 if $self->{binding_change};
3128 } else {
3129 $::STATUSBOX->add ("No action bound, no key or action specified!");
3130 $self->{binding_cancel}->()
3131 if $self->{binding_cancel};
3132 }
3133}
3134
3135sub start {
3136 my ($self) = @_;
3137
3138 $self->{rec_btn}->set_text ("stop recording");
3139 $self->{recording} = 1;
3140 $self->clear_command_list;
3141 $::CONN->start_record if $::CONN;
3142}
3143
3144sub stop {
3145 my ($self) = @_;
3146
3147 $self->{rec_btn}->set_text ("start recording");
3148 $self->{recording} = 0;
3149
3150 my $rec;
3151 $rec = $::CONN->stop_record if $::CONN;
3152 return unless ref $rec eq 'ARRAY';
3153 $self->set_command_list ($rec);
3154}
3155
3156# if $commit is true, the binding will be set after the user entered a key combo
3157sub ask_for_bind {
3158 my ($self, $commit) = @_;
3159
3160 CFClient::Binder::open_binding_dialog (sub {
3161 my ($mod, $sym) = @_;
3162 $self->{binding} = [$mod, $sym]; # XXX: how to stop that memleak?
3163 $self->update_binding_widgets;
3164 $self->commit if $commit;
3165 });
3166}
3167
3168# $mod and $sym are the modifiers and key symbol
3169# $cmds is a array ref of strings (the commands)
3170# $cb is the callback that is executed on OK
3171# $ccb is the callback that is executed on CANCEL and
3172# when the binding was unsuccessful on OK
3173sub set_binding {
3174 my ($self, $mod, $sym, $cmds, $cb, $ccb) = @_;
3175
3176 $self->clear_command_list;
3177 $self->{recording} = 0;
3178 $self->{rec_btn}->set_text ("start recording");
3179
3180 $self->{binding} = [$mod, $sym];
3181 $self->{commands} = $cmds;
3182
3183 $self->{binding_change} = $cb;
3184 $self->{binding_cancel} = $ccb;
3185
3186 $self->update_binding_widgets;
3187}
3188
3189# this is a shortcut method that asks for a binding
3190# and then just binds it.
3191sub do_quick_binding {
3192 my ($self, $cmds) = @_;
3193 $self->set_binding (undef, undef, $cmds, sub {
3194 $::CFG->{bindings}->{$_[0]}->{$_[1]} = $_[2];
3195 });
3196 $self->ask_for_bind (1);
3197}
3198
3199sub update_binding_widgets {
3200 my ($self) = @_;
3201 my ($mod, $sym, $cmds) = $self->get_binding;
3202 $self->{keylbl}->set_text (CFClient::Binder::keycombo_to_name ($mod, $sym));
3203 $self->set_command_list ($cmds);
3204}
3205
3206sub get_binding {
3207 my ($self) = @_;
3208 return (
3209 $self->{binding}->[0],
3210 $self->{binding}->[1],
3211 [ grep { defined $_ } @{$self->{commands}} ]
3212 );
3213}
3214
3215sub clear_command_list {
3216 my ($self) = @_;
3217 $self->{cmdbox}->clear ();
3218}
3219
3220sub set_command_list {
3221 my ($self, $cmds) = @_;
3222
3223 $self->{cmdbox}->clear ();
3224 $self->{commands} = $cmds;
3225
3226 my $idx = 0;
3227
3228 for (@$cmds) {
3229 $self->{cmdbox}->add (my $hb = new CFClient::UI::HBox);
3230
3231 my $i = $idx;
3232 $hb->add (new CFClient::UI::Label text => $_);
3233 $hb->add (new CFClient::UI::Button
3234 text => "delete",
3235 tooltip => "Deletes the action from the record",
3236 on_activate => sub {
3237 $self->{cmdbox}->remove ($hb);
3238 $cmds->[$i] = undef;
3239 });
3240
3241
3242 $idx++
3243 }
3244}
3245
3246#############################################################################
3247
3248package CFClient::UI::SpellList;
3249
3250our @ISA = CFClient::UI::FancyFrame::;
3251
3252sub new {
3253 my $class = shift;
3254
3255 my $self = $class->SUPER::new (binding => [], commands => [], @_);
3256
3257 $self->add (new CFClient::UI::ScrolledWindow
3258 scrolled => $self->{spellbox} = new CFClient::UI::Table);
3259
3260 $self;
3261}
3262
3263# XXX: Do sorting? Argl...
3264sub add_spell {
3265 my ($self, $spell) = @_;
3266 $self->{spells}->{$spell->{name}} = $spell;
3267
3268 $self->{spellbox}->add (0, $self->{tbl_idx}, new CFClient::UI::Face
3269 face => $spell->{face},
3270 can_hover => 1,
3271 can_events => 1,
3272 tooltip => $spell->{message});
3273
3274 $self->{spellbox}->add (1, $self->{tbl_idx}, new CFClient::UI::Label
3275 text => $spell->{name},
3276 can_hover => 1,
3277 can_events => 1,
3278 tooltip => $spell->{message},
3279 expand => 1);
3280
3281 $self->{spellbox}->add (2, $self->{tbl_idx}, new CFClient::UI::Label
3282 text => (sprintf "lvl: %2d sp: %2d dmg: %2d",
3283 $spell->{level}, ($spell->{mana} || $spell->{grace}), $spell->{damage}),
3284 expand => 1);
3285
3286 $self->{spellbox}->add (3, $self->{tbl_idx}++, new CFClient::UI::Button
3287 text => "bind to key",
3288 on_activate => sub { $::BIND_EDITOR->do_quick_binding (["cast $spell->{name}"]) });
3289}
3290
3291sub rebuild_spell_list {
3292 my ($self) = @_;
3293 $self->{tbl_idx} = 0;
3294 $self->add_spell ($_) for values %{$self->{spells}};
3295}
3296
3297sub remove_spell {
3298 my ($self, $spell) = @_;
3299 delete $self->{spells}->{$spell->{name}};
3300 $self->rebuild_spell_list;
3301}
3302
3303#############################################################################
3304
3009package CFClient::UI::Root; 3305package CFClient::UI::Root;
3010 3306
3011our @ISA = CFClient::UI::Container::; 3307our @ISA = CFClient::UI::Container::;
3012 3308
3013use CFClient::OpenGL; 3309use CFClient::OpenGL;
3122 $_->() 3418 $_->()
3123 for values %{delete $self->{refresh_hook}}; 3419 for values %{delete $self->{refresh_hook}};
3124 } 3420 }
3125 3421
3126 if ($self->{realloc}) { 3422 if ($self->{realloc}) {
3423 my %queue;
3127 my @queue; 3424 my @queue;
3425 my $widget;
3128 3426
3427 outer:
3129 while () { 3428 while () {
3130 if ($self->{realloc}) { 3429 if (my $realloc = delete $self->{realloc}) {
3131 #TODO use array-of-depth approach 3430 for $widget (values %$realloc) {
3431 $widget->{visible} or next; # do not resize invisible widgets
3132 3432
3133 use sort 'stable'; 3433 $queue{$widget+0}++ and next; # duplicates are common
3134 3434
3135 @queue = sort { $a->{visible} <=> $b->{visible} } 3435 push @{ $queue[$widget->{visible}] }, $widget;
3136 @queue, values %{delete $self->{realloc}}; 3436 }
3137 } 3437 }
3138 3438
3439 while () {
3440 @queue or last outer;
3441
3139 my $widget = pop @queue || last; 3442 $widget = pop @{ $queue[-1] || [] }
3443 and last;
3444
3445 pop @queue;
3446 }
3140 3447
3141 $widget->{visible} or last; # do not resize invisible widgets 3448 delete $queue{$widget+0};
3142 3449
3143 my ($w, $h) = $widget->size_request; 3450 my ($w, $h) = $widget->size_request;
3144 3451
3145 $w = List::Util::max $widget->{min_w}, $w + $widget->{padding_x} * 2; 3452 $w = List::Util::max $widget->{min_w}, $w + $widget->{padding_x} * 2;
3146 $h = List::Util::max $widget->{min_h}, $h + $widget->{padding_y} * 2; 3453 $h = List::Util::max $widget->{min_h}, $h + $widget->{padding_y} * 2;
3154 $widget->{req_h} = $h; 3461 $widget->{req_h} = $h;
3155 3462
3156 $self->{size_alloc}{$widget+0} = $widget; 3463 $self->{size_alloc}{$widget+0} = $widget;
3157 3464
3158 if (my $parent = $widget->{parent}) { 3465 if (my $parent = $widget->{parent}) {
3159 $self->{realloc}{$parent+0} = $parent; 3466 $self->{realloc}{$parent+0} = $parent
3160 #unshift @queue, $parent; 3467 unless $queue{$parent+0};
3468
3161 $parent->{force_size_alloc} = 1; 3469 $parent->{force_size_alloc} = 1;
3162 $self->{size_alloc}{$parent+0} = $parent; 3470 $self->{size_alloc}{$parent+0} = $parent;
3163 } 3471 }
3164 } 3472 }
3165 3473
3181 3489
3182 $w = int $w + 0.5; 3490 $w = int $w + 0.5;
3183 $h = int $h + 0.5; 3491 $h = int $h + 0.5;
3184 3492
3185 if ($widget->{w} != $w || $widget->{h} != $h || delete $widget->{force_size_alloc}) { 3493 if ($widget->{w} != $w || $widget->{h} != $h || delete $widget->{force_size_alloc}) {
3494 $widget->{old_w} = $widget->{w};
3495 $widget->{old_h} = $widget->{h};
3496
3186 $widget->{w} = $w; 3497 $widget->{w} = $w;
3187 $widget->{h} = $h; 3498 $widget->{h} = $h;
3188 3499
3189 $widget->emit (size_allocate => $w, $h); 3500 $widget->emit (size_allocate => $w, $h);
3190 } 3501 }
3205 glLoadIdentity; 3516 glLoadIdentity;
3206 glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000, 10000; 3517 glOrtho 0, $::WIDTH, $::HEIGHT, 0, -10000, 10000;
3207 glMatrixMode GL_MODELVIEW; 3518 glMatrixMode GL_MODELVIEW;
3208 glLoadIdentity; 3519 glLoadIdentity;
3209 3520
3521 {
3522 package CFClient::UI::Base;
3523
3524 ($draw_x, $draw_y, $draw_w, $draw_h) =
3525 (0, 0, $self->{w}, $self->{h});
3526 }
3527
3210 $self->_draw; 3528 $self->_draw;
3211} 3529}
3212 3530
3213############################################################################# 3531#############################################################################
3214 3532

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines