… | |
… | |
5 | |
5 | |
6 | use Scalar::Util (); |
6 | use Scalar::Util (); |
7 | use List::Util (); |
7 | use List::Util (); |
8 | |
8 | |
9 | use CFClient; |
9 | use CFClient; |
|
|
10 | use CFClient::Texture; |
10 | |
11 | |
11 | our ($FOCUS, $HOVER, $GRAB); # various widgets |
12 | our ($FOCUS, $HOVER, $GRAB); # various widgets |
12 | |
13 | |
|
|
14 | our $LAYOUT; |
13 | our $ROOT; |
15 | our $ROOT; |
14 | our $TOOLTIP; |
16 | our $TOOLTIP; |
15 | our $BUTTON_STATE; |
17 | our $BUTTON_STATE; |
16 | |
18 | |
17 | our %WIDGET; # all widgets, weak-referenced |
19 | our %WIDGET; # all widgets, weak-referenced |
|
|
20 | |
|
|
21 | sub get_layout { |
|
|
22 | for (grep { $_->{name} } values %WIDGET) { |
|
|
23 | $LAYOUT->{$_->{name}} = { |
|
|
24 | x => $_->{x} / $::WIDTH, |
|
|
25 | y => $_->{y} / $::HEIGHT, |
|
|
26 | w => $_->{w} / $::WIDTH, |
|
|
27 | h => $_->{h} / $::HEIGHT |
|
|
28 | }; |
|
|
29 | } |
|
|
30 | |
|
|
31 | return $LAYOUT; |
|
|
32 | } |
|
|
33 | |
|
|
34 | sub set_layout { |
|
|
35 | my ($layout) = @_; |
|
|
36 | $LAYOUT = $layout; |
|
|
37 | } |
18 | |
38 | |
19 | sub check_tooltip { |
39 | sub check_tooltip { |
20 | if (!$GRAB) { |
40 | if (!$GRAB) { |
21 | for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) { |
41 | for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) { |
22 | if (length $widget->{tooltip}) { |
42 | if (length $widget->{tooltip}) { |
… | |
… | |
193 | } |
213 | } |
194 | } |
214 | } |
195 | |
215 | |
196 | Scalar::Util::weaken ($CFClient::UI::WIDGET{$self+0} = $self); |
216 | Scalar::Util::weaken ($CFClient::UI::WIDGET{$self+0} = $self); |
197 | |
217 | |
|
|
218 | if (my $layout = $CFClient::UI::LAYOUT->{$self->{name}}) { |
|
|
219 | $self->{user_x} = $layout->{x} * $::WIDTH; |
|
|
220 | $self->{user_y} = $layout->{y} * $::HEIGHT; |
|
|
221 | $self->{user_w} = ($layout->{w} != 0 ? $layout->{w} : 1) * $::WIDTH; |
|
|
222 | $self->{user_h} = ($layout->{h} != 0 ? $layout->{h} : 1) * $::HEIGHT; |
|
|
223 | } |
|
|
224 | |
198 | $self |
225 | $self |
199 | } |
226 | } |
200 | |
227 | |
201 | sub destroy { |
228 | sub destroy { |
202 | my ($self) = @_; |
229 | my ($self) = @_; |
… | |
… | |
228 | sub set_invisible { |
255 | sub set_invisible { |
229 | my ($self) = @_; |
256 | my ($self) = @_; |
230 | |
257 | |
231 | # broken show/hide model |
258 | # broken show/hide model |
232 | |
259 | |
|
|
260 | delete $self->{root}; |
233 | delete $self->{visible}; |
261 | delete $self->{visible}; |
234 | |
262 | |
235 | undef $GRAB if $GRAB == $self; |
263 | undef $GRAB if $GRAB == $self; |
236 | undef $HOVER if $HOVER == $self; |
264 | undef $HOVER if $HOVER == $self; |
237 | |
265 | |
… | |
… | |
458 | sub set_parent { |
486 | sub set_parent { |
459 | my ($self, $parent) = @_; |
487 | my ($self, $parent) = @_; |
460 | |
488 | |
461 | Scalar::Util::weaken ($self->{parent} = $parent); |
489 | Scalar::Util::weaken ($self->{parent} = $parent); |
462 | |
490 | |
|
|
491 | $self->{root} = $parent->{root}; |
|
|
492 | $self->{visible} = $parent->{visible} + 1; |
|
|
493 | |
463 | # TODO: req_w _does_change after ->reconfigure |
494 | # TODO: req_w _does_change after ->reconfigure |
464 | $self->check_size |
495 | $self->check_size |
465 | unless exists $self->{req_w}; |
496 | unless exists $self->{req_w}; |
466 | |
497 | |
467 | $self->show; |
498 | $self->show; |
… | |
… | |
618 | delete $child->{parent}; |
649 | delete $child->{parent}; |
619 | $child->hide; |
650 | $child->hide; |
620 | |
651 | |
621 | $self->{children} = [ grep $_ != $child, @{ $self->{children} } ]; |
652 | $self->{children} = [ grep $_ != $child, @{ $self->{children} } ]; |
622 | |
653 | |
623 | $self->check_size; |
654 | $self->check_size (1); |
624 | $self->update; |
655 | $self->update; |
625 | } |
656 | } |
626 | |
657 | |
627 | sub clear { |
658 | sub clear { |
628 | my ($self) = @_; |
659 | my ($self) = @_; |
… | |
… | |
871 | $self->{vp}->add ($self->{scrolled}); |
902 | $self->{vp}->add ($self->{scrolled}); |
872 | $self->add ($self->{vp}); |
903 | $self->add ($self->{vp}); |
873 | $self->add ($self->{slider}); |
904 | $self->add ($self->{slider}); |
874 | |
905 | |
875 | $self |
906 | $self |
|
|
907 | } |
|
|
908 | |
|
|
909 | sub update { |
|
|
910 | my ($self) = @_; |
|
|
911 | |
|
|
912 | $self->SUPER::update; |
|
|
913 | |
|
|
914 | # todo: overwrite size_allocate of child |
|
|
915 | my $child = $self->{vp}->child; |
|
|
916 | $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]); |
876 | } |
917 | } |
877 | |
918 | |
878 | sub size_allocate { |
919 | sub size_allocate { |
879 | my ($self, $w, $h) = @_; |
920 | my ($self, $w, $h) = @_; |
880 | |
921 | |
… | |
… | |
1101 | col_expand => [], |
1142 | col_expand => [], |
1102 | @_, |
1143 | @_, |
1103 | ) |
1144 | ) |
1104 | } |
1145 | } |
1105 | |
1146 | |
|
|
1147 | sub children { |
|
|
1148 | grep $_, map @$_, grep $_, @{ $_[0]{children} } |
|
|
1149 | } |
|
|
1150 | |
1106 | sub add { |
1151 | sub add { |
1107 | my ($self, $x, $y, $child) = @_; |
1152 | my ($self, $x, $y, $child) = @_; |
1108 | |
1153 | |
1109 | $child->set_parent ($self); |
1154 | $child->set_parent ($self); |
1110 | $self->{children}[$y][$x] = $child; |
1155 | $self->{children}[$y][$x] = $child; |
1111 | |
1156 | |
1112 | $child->check_size; |
1157 | $self->check_size (1); |
1113 | } |
1158 | } |
1114 | |
1159 | |
1115 | sub children { |
|
|
1116 | grep $_, map @$_, grep $_, @{ $_[0]{children} } |
|
|
1117 | } |
|
|
1118 | |
|
|
1119 | # TODO: move to container class maybe? send childs a signal on removal? |
1160 | # TODO: move to container class maybe? send children a signal on removal? |
1120 | sub clear { |
1161 | sub clear { |
1121 | my ($self) = @_; |
1162 | my ($self) = @_; |
1122 | |
1163 | |
1123 | my @children = $self->children; |
1164 | my @children = $self->children; |
1124 | delete $self->{children}; |
1165 | delete $self->{children}; |
… | |
… | |
1126 | for (@children) { |
1167 | for (@children) { |
1127 | delete $_->{parent}; |
1168 | delete $_->{parent}; |
1128 | $_->hide; |
1169 | $_->hide; |
1129 | } |
1170 | } |
1130 | |
1171 | |
|
|
1172 | $self->check_size (1); |
1131 | $self->update; |
1173 | $self->update; |
1132 | } |
1174 | } |
1133 | |
1175 | |
1134 | sub get_wh { |
1176 | sub get_wh { |
1135 | my ($self) = @_; |
1177 | my ($self) = @_; |
… | |
… | |
1167 | sub size_allocate { |
1209 | sub size_allocate { |
1168 | my ($self, $w, $h) = @_; |
1210 | my ($self, $w, $h) = @_; |
1169 | |
1211 | |
1170 | my ($ws, $hs) = $self->get_wh; |
1212 | my ($ws, $hs) = $self->get_wh; |
1171 | |
1213 | |
1172 | my $req_w = sum @$ws; |
1214 | my $req_w = (sum @$ws) || 1; |
1173 | my $req_h = sum @$hs; |
1215 | my $req_h = (sum @$hs) || 1; |
1174 | |
1216 | |
1175 | # TODO: nicer code && do row_expand |
1217 | # TODO: nicer code && do row_expand |
1176 | my @col_expand = @{$self->{col_expand}}; |
1218 | my @col_expand = @{$self->{col_expand}}; |
1177 | @col_expand = (1) x @$ws unless @col_expand; |
1219 | @col_expand = (1) x @$ws unless @col_expand; |
1178 | my $col_expand = (sum @col_expand) || 1; |
1220 | my $col_expand = (sum @col_expand) || 1; |
… | |
… | |
2132 | } |
2174 | } |
2133 | |
2175 | |
2134 | sub set_range { |
2176 | sub set_range { |
2135 | my ($self, $range) = @_; |
2177 | my ($self, $range) = @_; |
2136 | |
2178 | |
2137 | $self->{range} = $range; |
2179 | ($range, $self->{range}) = ($self->{range}, $range); |
2138 | |
2180 | |
2139 | $self->update; |
2181 | $self->update |
|
|
2182 | if "@$range" ne "@{$self->{range}}"; |
2140 | } |
2183 | } |
2141 | |
2184 | |
2142 | sub set_value { |
2185 | sub set_value { |
2143 | my ($self, $value) = @_; |
2186 | my ($self, $value) = @_; |
2144 | |
2187 | |
… | |
… | |
2709 | $self->SUPER::DESTROY; |
2752 | $self->SUPER::DESTROY; |
2710 | } |
2753 | } |
2711 | |
2754 | |
2712 | ############################################################################# |
2755 | ############################################################################# |
2713 | |
2756 | |
2714 | package CFClient::UI::InventoryItem; |
|
|
2715 | |
|
|
2716 | our @ISA = CFClient::UI::HBox::; |
|
|
2717 | |
|
|
2718 | sub new { |
|
|
2719 | my $class = shift; |
|
|
2720 | |
|
|
2721 | my %args = @_; |
|
|
2722 | |
|
|
2723 | my $item = delete $args{item}; |
|
|
2724 | |
|
|
2725 | my $desc = CFClient::Item::desc_string $item; |
|
|
2726 | |
|
|
2727 | my $self = $class->SUPER::new ( |
|
|
2728 | can_hover => 1, |
|
|
2729 | can_events => 1, |
|
|
2730 | tooltip => ((CFClient::UI::Label::escape $desc) |
|
|
2731 | . "\n<small>leftclick - examine\nshift+leftclick - move/pickup/drop\nmiddle click - apply\nrightclick - menu</small>"), |
|
|
2732 | connect_button_down => sub { |
|
|
2733 | my ($self, $ev, $x, $y) = @_; |
|
|
2734 | |
|
|
2735 | # todo: maybe put examine on 1? but should just be a tooltip :( |
|
|
2736 | if (($ev->{mod} & CFClient::KMOD_SHIFT) && $ev->{button} == 1) { |
|
|
2737 | my $targ = $::CONN->{player}{tag}; |
|
|
2738 | |
|
|
2739 | if ($item->{container} == $::CONN->{player}{tag}) { |
|
|
2740 | $targ = $main::OPENCONT; |
|
|
2741 | } |
|
|
2742 | |
|
|
2743 | $::CONN->send ("move $targ $item->{tag} 0"); |
|
|
2744 | } elsif ($ev->{button} == 1) { |
|
|
2745 | $::CONN->send ("examine $item->{tag}"); |
|
|
2746 | } elsif ($ev->{button} == 2) { |
|
|
2747 | $::CONN->send ("apply $item->{tag}"); |
|
|
2748 | } elsif ($ev->{button} == 3) { |
|
|
2749 | my @menu_items = ( |
|
|
2750 | ["examine", sub { $::CONN->send ("examine $item->{tag}") }], |
|
|
2751 | ["mark", sub { $::CONN->send ("mark ". pack "N", $item->{tag}) }], |
|
|
2752 | ["apply", sub { $::CONN->send ("apply $item->{tag}") }], |
|
|
2753 | ( |
|
|
2754 | $item->{flags} & Crossfire::Protocol::F_LOCKED |
|
|
2755 | ? ( |
|
|
2756 | ["unlock", sub { $::CONN->send ("lock " . pack "CN", 0, $item->{tag}) }], |
|
|
2757 | ) |
|
|
2758 | : ( |
|
|
2759 | ["lock", sub { $::CONN->send ("lock " . pack "CN", 1, $item->{tag}) }], |
|
|
2760 | ["drop", sub { $::CONN->send ("move $main::OPENCONT $item->{tag} 0") }], |
|
|
2761 | ) |
|
|
2762 | ), |
|
|
2763 | ); |
|
|
2764 | |
|
|
2765 | CFClient::UI::Menu->new (items => \@menu_items)->popup ($ev); |
|
|
2766 | } |
|
|
2767 | |
|
|
2768 | 1 |
|
|
2769 | }, |
|
|
2770 | %args |
|
|
2771 | ); |
|
|
2772 | |
|
|
2773 | |
|
|
2774 | $self->add (new CFClient::UI::Face |
|
|
2775 | can_events => 0, |
|
|
2776 | face => $item->{face}, |
|
|
2777 | anim => $item->{anim}, |
|
|
2778 | animspeed => $item->{animspeed}, |
|
|
2779 | ); |
|
|
2780 | |
|
|
2781 | $self->add ($self->{name_lbl} = new CFClient::UI::Label can_events => 0); |
|
|
2782 | |
|
|
2783 | $self->{item} = $item; |
|
|
2784 | |
|
|
2785 | $self->update_item; |
|
|
2786 | |
|
|
2787 | $self |
|
|
2788 | } |
|
|
2789 | |
|
|
2790 | sub update_item { |
|
|
2791 | my ($self) = @_; |
|
|
2792 | |
|
|
2793 | my $desc = CFClient::Item::desc_string ($self->{item}); |
|
|
2794 | |
|
|
2795 | $self->{name_lbl}->set_text ($desc); |
|
|
2796 | } |
|
|
2797 | |
|
|
2798 | ############################################################################# |
|
|
2799 | |
|
|
2800 | package CFClient::UI::Inventory; |
2757 | package CFClient::UI::Inventory; |
2801 | |
2758 | |
2802 | our @ISA = CFClient::UI::ScrolledWindow::; |
2759 | our @ISA = CFClient::UI::ScrolledWindow::; |
2803 | |
2760 | |
2804 | sub new { |
2761 | sub new { |
… | |
… | |
2833 | $self->{scrolled}->add (1, $row, $item->{desc_widget}); |
2790 | $self->{scrolled}->add (1, $row, $item->{desc_widget}); |
2834 | $self->{scrolled}->add (2, $row, $item->{weight_widget}); |
2791 | $self->{scrolled}->add (2, $row, $item->{weight_widget}); |
2835 | |
2792 | |
2836 | $row++; |
2793 | $row++; |
2837 | } |
2794 | } |
2838 | |
|
|
2839 | # $range->{range} = [$self->{pos}, 0, $self->{max_pos}, $page]; |
|
|
2840 | } |
2795 | } |
2841 | |
2796 | |
2842 | sub size_request { |
2797 | sub size_request { |
2843 | my ($self) = @_; |
2798 | my ($self) = @_; |
2844 | ($self->{req_w}, $self->{req_h}); |
2799 | ($self->{req_w}, $self->{req_h}); |
… | |
… | |
3036 | |
2991 | |
3037 | sub new { |
2992 | sub new { |
3038 | my $class = shift; |
2993 | my $class = shift; |
3039 | |
2994 | |
3040 | $class->SUPER::new ( |
2995 | $class->SUPER::new ( |
|
|
2996 | visible => 1, |
3041 | @_, |
2997 | @_, |
3042 | ) |
2998 | ) |
3043 | } |
2999 | } |
3044 | |
3000 | |
3045 | sub configure { |
3001 | sub configure { |
… | |
… | |
3103 | sub add { |
3059 | sub add { |
3104 | my ($self, @children) = @_; |
3060 | my ($self, @children) = @_; |
3105 | |
3061 | |
3106 | for (my @widgets = @children; my $w = pop @widgets; ) { |
3062 | for (my @widgets = @children; my $w = pop @widgets; ) { |
3107 | push @widgets, $w->children; |
3063 | push @widgets, $w->children; |
3108 | $w->{root} = $self; |
3064 | $w->{root} = $self; |
3109 | $w->{visible} = 1; |
3065 | $w->{visible} = $self->{visible} + 1; |
3110 | } |
3066 | } |
3111 | |
3067 | |
3112 | for my $child (@children) { |
3068 | for my $child (@children) { |
3113 | $child->{is_toplevel} = 1; |
3069 | $child->{is_toplevel} = 1; |
3114 | |
3070 | |