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.309 by elmex, Wed Jun 21 12:59:23 2006 UTC vs.
Revision 1.328 by root, Sat Jul 22 13:43:05 2006 UTC

82} 82}
83 83
84sub feed_sdl_button_down_event { 84sub feed_sdl_button_down_event {
85 my ($ev) = @_; 85 my ($ev) = @_;
86 my ($x, $y) = ($ev->{x}, $ev->{y}); 86 my ($x, $y) = ($ev->{x}, $ev->{y});
87
88 warn "button down $ev->{button}\n";#d#
87 89
88 if (!$BUTTON_STATE) { 90 if (!$BUTTON_STATE) {
89 my $widget = $ROOT->find_widget ($x, $y); 91 my $widget = $ROOT->find_widget ($x, $y);
90 92
91 $GRAB = $widget; 93 $GRAB = $widget;
335sub size_request { 337sub size_request {
336 require Carp; 338 require Carp;
337 Carp::confess "size_request is abstract"; 339 Carp::confess "size_request is abstract";
338} 340}
339 341
342sub baseline_shift {
343 0
344}
345
340sub configure { 346sub configure {
341 my ($self, $x, $y, $w, $h) = @_; 347 my ($self, $x, $y, $w, $h) = @_;
342 348
343 if ($self->{aspect}) { 349 if ($self->{aspect}) {
344 my ($ow, $oh) = ($w, $h); 350 my ($ow, $oh) = ($w, $h);
419 my ($self) = @_; 425 my ($self) = @_;
420 426
421 return if $FOCUS == $self; 427 return if $FOCUS == $self;
422 return unless $self->{can_focus}; 428 return unless $self->{can_focus};
423 429
424 my $focus = $FOCUS; $FOCUS = $self; 430 $FOCUS = $self;
425 431
426 $focus->update if $focus; 432 $self->update;
427 $FOCUS->update;
428 433
429 0 434 0
430} 435}
431 436
432sub invoke_focus_out { 437sub invoke_focus_out {
433 my ($self) = @_; 438 my ($self) = @_;
434 439
435 return unless $FOCUS == $self; 440 return unless $FOCUS == $self;
436 441
437 my $focus = $FOCUS; undef $FOCUS; 442 undef $FOCUS;
438 443
439 $focus->update if $focus; #? 444 $self->update;
440 445
441 $::MAPWIDGET->grab_focus #d# focus mapwidget if no other widget has focus 446 $::MAPWIDGET->grab_focus #d# focus mapwidget if no other widget has focus
442 unless $FOCUS; 447 unless $FOCUS;
443 448
444 0 449 0
445} 450}
446 451
447sub grab_focus { 452sub grab_focus {
448 my ($self) = @_; 453 my ($self) = @_;
449 454
455 $FOCUS->emit ("focus_out") if $FOCUS;
450 $self->emit ("focus_in"); 456 $self->emit ("focus_in");
451} 457}
452 458
453sub invoke_mouse_motion { 1 } 459sub invoke_mouse_motion { 0 }
454sub invoke_button_up { 1 } 460sub invoke_button_up { 0 }
455sub invoke_key_down { 1 } 461sub invoke_key_down { 0 }
456sub invoke_key_up { 1 } 462sub invoke_key_up { 0 }
457 463
458sub invoke_button_down { 464sub invoke_button_down {
459 my ($self, $ev, $x, $y) = @_; 465 my ($self, $ev, $x, $y) = @_;
460 466
461 $self->grab_focus; 467 $self->grab_focus;
462 468
469 warn "button down $ev->{button} $x $y\n";#d#
470
463 1 471 0
464} 472}
465 473
466sub connect { 474sub connect {
467 my ($self, $signal, $cb) = @_; 475 my ($self, $signal, $cb) = @_;
468 476
535 return unless $self->{h} && $self->{w}; 543 return unless $self->{h} && $self->{w};
536 544
537 # update screen rectangle 545 # update screen rectangle
538 local $draw_x = $draw_x + $self->{x}; 546 local $draw_x = $draw_x + $self->{x};
539 local $draw_y = $draw_y + $self->{y}; 547 local $draw_y = $draw_y + $self->{y};
540 local $draw_w = $draw_x + $self->{w};
541 local $draw_h = $draw_y + $self->{h};
542 548
543 # skip widgets that are entirely outside the drawing area 549 # skip widgets that are entirely outside the drawing area
544 return if ($draw_x + $self->{w} < 0) || ($draw_x >= $draw_w) 550 return if ($draw_x + $self->{w} < 0) || ($draw_x >= $draw_w)
545 || ($draw_y + $self->{h} < 0) || ($draw_y >= $draw_h); 551 || ($draw_y + $self->{h} < 0) || ($draw_y >= $draw_h);
546 552
585} 591}
586 592
587sub DESTROY { 593sub DESTROY {
588 my ($self) = @_; 594 my ($self) = @_;
589 595
596 return if CFClient::in_destruct;
597
590 delete $WIDGET{$self+0}; 598 delete $WIDGET{$self+0};
591 599
592 eval { $self->destroy }; 600 eval { $self->destroy };
593 warn "exception during widget destruction: $@" if $@ & $@ != /during global destruction/; 601 warn "exception during widget destruction: $@" if $@ & $@ != /during global destruction/;
594} 602}
984 $self->add ($child) if $child; 992 $self->add ($child) if $child;
985 993
986 $self 994 $self
987} 995}
988 996
997#TODO# update range on size_allocate depending on child
998
989sub add { 999sub add {
990 my ($self, $widget) = @_; 1000 my ($self, $widget) = @_;
991 1001
992 $self->{vp}->add ($self->{child} = $widget); 1002 $self->{vp}->add ($self->{child} = $widget);
993} 1003}
994 1004
1005sub invoke_button_down {
1006 my ($self, $ev) = @_;
1007
1008 warn "button down $ev->{button}\n";#d#
1009
1010 0
1011}
1012
1013sub update_slider {
1014 my ($self) = @_;
1015
1016 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $self->{vp}->child->{h}, $self->{vp}{h}, 1]);
1017}
1018
995sub update { 1019sub update {
996 my ($self) = @_; 1020 my ($self) = @_;
997 1021
998 $self->SUPER::update; 1022 $self->SUPER::update;
999 1023
1000 # todo: overwrite size_allocate of child 1024 $self->update_slider;
1001 my $child = $self->{vp}->child;
1002 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]);
1003} 1025}
1004 1026
1005sub invoke_size_allocate { 1027sub invoke_size_allocate {
1006 my ($self, $w, $h) = @_; 1028 my ($self, $w, $h) = @_;
1007 1029
1008 my $child = $self->{vp}->child; 1030 $self->update_slider;
1009 $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]);
1010 1031
1011 $self->SUPER::invoke_size_allocate ($w, $h) 1032 $self->SUPER::invoke_size_allocate ($w, $h)
1012} 1033}
1013
1014#TODO# update range on size_allocate depending on child
1015# update viewport offset on scroll
1016 1034
1017############################################################################# 1035#############################################################################
1018 1036
1019package CFClient::UI::Frame; 1037package CFClient::UI::Frame;
1020 1038
1076 my $self = $class->SUPER::new ( 1094 my $self = $class->SUPER::new (
1077 bg => [1, 1, 1, 1], 1095 bg => [1, 1, 1, 1],
1078 border_bg => [1, 1, 1, 1], 1096 border_bg => [1, 1, 1, 1],
1079 border => 0.6, 1097 border => 0.6,
1080 can_events => 1, 1098 can_events => 1,
1081 min_w => 16, 1099 min_w => 64,
1082 min_h => 16, 1100 min_h => 32,
1083 %arg, 1101 %arg,
1084 ); 1102 );
1085 1103
1086 $self->{title_widget} = new CFClient::UI::Label 1104 $self->{title_widget} = new CFClient::UI::Label
1087 align => 0, 1105 align => 0,
1091 if exists $self->{title}; 1109 if exists $self->{title};
1092 1110
1093 if ($self->{has_close_button}) { 1111 if ($self->{has_close_button}) {
1094 $self->{close_button} = 1112 $self->{close_button} =
1095 new CFClient::UI::ImageButton 1113 new CFClient::UI::ImageButton
1096 image => 'x1_close.png', 1114 path => 'x1_close.png',
1097 on_activate => sub { $self->hide }; 1115 on_activate => sub { $self->emit ("delete") };
1098 1116
1099 $self->CFClient::UI::Container::add ($self->{close_button}); 1117 $self->CFClient::UI::Container::add ($self->{close_button});
1100 } 1118 }
1101 1119
1102 $self 1120 $self
1148 $self->child->configure ($border, $border, $w, $h); 1166 $self->child->configure ($border, $border, $w, $h);
1149 1167
1150 $self->{close_button}->configure ($self->{w} - $border, 0, $border, $border) 1168 $self->{close_button}->configure ($self->{w} - $border, 0, $border, $border)
1151 if $self->{close_button}; 1169 if $self->{close_button};
1152 1170
1171 1
1172}
1173
1174sub invoke_delete {
1175 my ($self) = @_;
1176
1177 $self->hide;
1178
1153 1 1179 1
1154} 1180}
1155 1181
1156sub invoke_button_down { 1182sub invoke_button_down {
1157 my ($self, $ev, $x, $y) = @_; 1183 my ($self, $ev, $x, $y) = @_;
1438 1464
1439sub invoke_size_allocate { 1465sub invoke_size_allocate {
1440 my ($self, $w, $h) = @_; 1466 my ($self, $w, $h) = @_;
1441 1467
1442 my $space = $self->{vertical} ? $h : $w; 1468 my $space = $self->{vertical} ? $h : $w;
1443 my $children = $self->{children}; 1469 my @children = $self->visible_children;
1444 1470
1445 my @req; 1471 my @req;
1446 1472
1447 if ($self->{homogeneous}) { 1473 if ($self->{homogeneous}) {
1448 @req = ($space / (@$children || 1)) x @$children; 1474 @req = ($space / (@children || 1)) x @children;
1449 } else { 1475 } else {
1450 @req = map $_->{$self->{vertical} ? "req_h" : "req_w"}, @$children; 1476 @req = map $_->{$self->{vertical} ? "req_h" : "req_w"}, @children;
1451 my $req = List::Util::sum @req; 1477 my $req = List::Util::sum @req;
1452 1478
1453 if ($req > $space) { 1479 if ($req > $space) {
1454 # ah well, not enough space 1480 # ah well, not enough space
1455 $_ *= $space / $req for @req; 1481 $_ *= $space / $req for @req;
1456 } else { 1482 } else {
1457 my $expand = (List::Util::sum map $_->{expand}, @$children) || 1; 1483 my $expand = (List::Util::sum map $_->{expand}, @children) || 1;
1458 1484
1459 $space = ($space - $req) / $expand; # remaining space to give away 1485 $space = ($space - $req) / $expand; # remaining space to give away
1460 1486
1461 $req[$_] += $space * $children->[$_]{expand} 1487 $req[$_] += $space * $children[$_]{expand}
1462 for 0 .. $#$children; 1488 for 0 .. $#children;
1463 } 1489 }
1464 } 1490 }
1465 1491
1466 CFClient::UI::harmonize \@req; 1492 CFClient::UI::harmonize \@req;
1467 1493
1468 my $pos = 0; 1494 my $pos = 0;
1469 for (0 .. $#$children) { 1495 for (0 .. $#children) {
1470 my $alloc = $req[$_]; 1496 my $alloc = $req[$_];
1471 $children->[$_]->configure ($self->{vertical} ? (0, $pos, $w, $alloc) : ($pos, 0, $alloc, $h)); 1497 $children[$_]->configure ($self->{vertical} ? (0, $pos, $w, $alloc) : ($pos, 0, $alloc, $h));
1472 1498
1473 $pos += $alloc; 1499 $pos += $alloc;
1474 } 1500 }
1475 1501
1476 1 1502 1
1579 my ($self, $text) = @_; 1605 my ($self, $text) = @_;
1580 1606
1581 return if $self->{text} eq "T$text"; 1607 return if $self->{text} eq "T$text";
1582 $self->{text} = "T$text"; 1608 $self->{text} = "T$text";
1583 1609
1584 $self->{layout} = new CFClient::Layout if $self->{layout}->is_rgba;
1585 $self->{layout}->set_text ($text); 1610 $self->{layout}->set_text ($text);
1586 1611
1587 delete $self->{size_req}; 1612 delete $self->{size_req};
1588 $self->realloc; 1613 $self->realloc;
1589 $self->update; 1614 $self->update;
1595 return if $self->{text} eq "M$markup"; 1620 return if $self->{text} eq "M$markup";
1596 $self->{text} = "M$markup"; 1621 $self->{text} = "M$markup";
1597 1622
1598 my $rgba = $markup =~ /span.*(?:foreground|background)/; 1623 my $rgba = $markup =~ /span.*(?:foreground|background)/;
1599 1624
1600 $self->{layout} = new CFClient::Layout $rgba if $self->{layout}->is_rgba != $rgba;
1601 $self->{layout}->set_markup ($markup); 1625 $self->{layout}->set_markup ($markup);
1602 1626
1603 delete $self->{size_req}; 1627 delete $self->{size_req};
1604 $self->realloc; 1628 $self->realloc;
1605 $self->update; 1629 $self->update;
1617 1641
1618 my ($w, $h) = $self->{layout}->size; 1642 my ($w, $h) = $self->{layout}->size;
1619 1643
1620 if (exists $self->{template}) { 1644 if (exists $self->{template}) {
1621 $self->{template}->set_font ($self->{font}) if $self->{font}; 1645 $self->{template}->set_font ($self->{font}) if $self->{font};
1646 $self->{template}->set_width ($self->{max_w} || -1);
1622 $self->{template}->set_height ($self->{fontsize} * $::FONTSIZE); 1647 $self->{template}->set_height ($self->{fontsize} * $::FONTSIZE);
1623 1648
1624 my ($w2, $h2) = $self->{template}->size; 1649 my ($w2, $h2) = $self->{template}->size;
1625 1650
1626 $w = List::Util::max $w, $w2; 1651 $w = List::Util::max $w, $w2;
1631 }; 1656 };
1632 1657
1633 @{ $self->{size_req} } 1658 @{ $self->{size_req} }
1634} 1659}
1635 1660
1661sub baseline_shift {
1662 $_[0]{layout}->descent
1663}
1664
1636sub invoke_size_allocate { 1665sub invoke_size_allocate {
1637 my ($self, $w, $h) = @_; 1666 my ($self, $w, $h) = @_;
1638 1667
1639 delete $self->{ox}; 1668 delete $self->{ox};
1640 1669
1646 1675
1647sub set_fontsize { 1676sub set_fontsize {
1648 my ($self, $fontsize) = @_; 1677 my ($self, $fontsize) = @_;
1649 1678
1650 $self->{fontsize} = $fontsize; 1679 $self->{fontsize} = $fontsize;
1680 delete $self->{size_req};
1651 delete $self->{texture}; 1681 delete $self->{texture};
1652 1682
1653 $self->realloc; 1683 $self->realloc;
1654} 1684}
1655 1685
1656sub reconfigure { 1686sub reconfigure {
1657 my ($self) = @_; 1687 my ($self) = @_;
1658 1688
1659 delete $self->{size_req}; 1689 delete $self->{size_req};
1690 delete $self->{texture};
1660 1691
1661 $self->SUPER::reconfigure; 1692 $self->SUPER::reconfigure;
1662} 1693}
1663 1694
1664sub _draw { 1695sub _draw {
1665 my ($self) = @_; 1696 my ($self) = @_;
1666 1697
1667 $self->SUPER::_draw; # draw background, if applicable 1698 $self->SUPER::_draw; # draw background, if applicable
1668 1699
1669 my $tex = $self->{texture} ||= do { 1700 my $size = $self->{texture} ||= do {
1670 $self->{layout}->set_foreground (@{$self->{fg}}); 1701 $self->{layout}->set_foreground (@{$self->{fg}});
1671 $self->{layout}->set_font ($self->{font}) if $self->{font}; 1702 $self->{layout}->set_font ($self->{font}) if $self->{font};
1672 $self->{layout}->set_width ($self->{w}); 1703 $self->{layout}->set_width ($self->{w});
1673 $self->{layout}->set_ellipsise ($self->{ellipsise}); 1704 $self->{layout}->set_ellipsise ($self->{ellipsise});
1674 $self->{layout}->set_single_paragraph_mode ($self->{ellipsise}); 1705 $self->{layout}->set_single_paragraph_mode ($self->{ellipsise});
1675 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); 1706 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE);
1676 1707
1677 new_from_layout CFClient::Texture $self->{layout} 1708 [$self->{layout}->size]
1678 }; 1709 };
1679 1710
1680 unless (exists $self->{ox}) { 1711 unless (exists $self->{ox}) {
1681 $self->{ox} = int ($self->{align} < 0 ? $self->{padding_x} 1712 $self->{ox} = int ($self->{align} < 0 ? $self->{padding_x}
1682 : $self->{align} > 0 ? $self->{w} - $tex->{w} - $self->{padding_x} 1713 : $self->{align} > 0 ? $self->{w} - $size->[0] - $self->{padding_x}
1683 : ($self->{w} - $tex->{w}) * 0.5); 1714 : ($self->{w} - $size->[0]) * 0.5);
1684 1715
1685 $self->{oy} = int ($self->{valign} < 0 ? $self->{padding_y} 1716 $self->{oy} = int ($self->{valign} < 0 ? $self->{padding_y}
1686 : $self->{valign} > 0 ? $self->{h} - $tex->{h} - $self->{padding_y} 1717 : $self->{valign} > 0 ? $self->{h} - $size->[1] - $self->{padding_y}
1687 : ($self->{h} - $tex->{h}) * 0.5); 1718 : ($self->{h} - $size->[1]) * 0.5);
1688 }; 1719 };
1689 1720
1690 glEnable GL_TEXTURE_2D;
1691
1692 my $w = List::Util::min $self->{w} + 4, $tex->{w}; 1721 my $w = List::Util::min $self->{w} + 4, $size->[0];
1693 my $h = List::Util::min $self->{h} + 2, $tex->{h}; 1722 my $h = List::Util::min $self->{h} + 2, $size->[1];
1694 1723
1695 if ($tex->{format} == GL_ALPHA) { 1724 $self->{layout}->render ($self->{ox}, $self->{oy});
1696 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE;
1697 glColor @{$self->{fg}};
1698 $tex->draw_quad_alpha ($self->{ox}, $self->{oy}, $w, $h);
1699 } else {
1700 glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE;
1701 $tex->draw_quad_alpha_premultiplied ($self->{ox}, $self->{oy}, $w, $h);
1702 }
1703
1704 glDisable GL_TEXTURE_2D;
1705} 1725}
1706 1726
1707############################################################################# 1727#############################################################################
1708 1728
1709package CFClient::UI::EntryBase; 1729package CFClient::UI::EntryBase;
1820 1840
1821 my $idx = $self->{layout}->xy_to_index ($x, $y); 1841 my $idx = $self->{layout}->xy_to_index ($x, $y);
1822 1842
1823 # byte-index to char-index 1843 # byte-index to char-index
1824 my $text = $self->{text}; 1844 my $text = $self->{text};
1825 utf8::encode $text; 1845 utf8::encode $text; $text = substr $text, 0, $idx; utf8::decode $text;
1826 $self->{cursor} = length substr $text, 0, $idx; 1846 $self->{cursor} = length $text;
1827 1847
1828 $self->_set_text ($self->{text}); 1848 $self->_set_text ($self->{text});
1829 $self->update; 1849 $self->update;
1830 1850
1831 1 1851 1
2051 my ($self) = @_; 2071 my ($self) = @_;
2052 2072
2053 (6) x 2 2073 (6) x 2
2054} 2074}
2055 2075
2076sub toggle {
2077 my ($self) = @_;
2078
2079 $self->{state} = !$self->{state};
2080 $self->emit (changed => $self->{state});
2081 $self->update;
2082}
2083
2056sub invoke_button_down { 2084sub invoke_button_down {
2057 my ($self, $ev, $x, $y) = @_; 2085 my ($self, $ev, $x, $y) = @_;
2058 2086
2059 if ($x >= $self->{padding_x} && $x < $self->{w} - $self->{padding_x} 2087 if ($x >= $self->{padding_x} && $x < $self->{w} - $self->{padding_x}
2060 && $y >= $self->{padding_y} && $y < $self->{h} - $self->{padding_y}) { 2088 && $y >= $self->{padding_y} && $y < $self->{h} - $self->{padding_y}) {
2061 $self->{state} = !$self->{state}; 2089 $self->toggle;
2062 $self->emit (changed => $self->{state});
2063 } else { 2090 } else {
2064 return 0 2091 return 0
2065 } 2092 }
2066 2093
2067 1 2094 1
2092package CFClient::UI::Image; 2119package CFClient::UI::Image;
2093 2120
2094our @ISA = CFClient::UI::Base::; 2121our @ISA = CFClient::UI::Base::;
2095 2122
2096use CFClient::OpenGL; 2123use CFClient::OpenGL;
2097use Carp qw/confess/;
2098 2124
2099our %loaded_images; 2125our %texture_cache;
2100 2126
2101sub new { 2127sub new {
2102 my $class = shift; 2128 my $class = shift;
2103 2129
2104 my $self = $class->SUPER::new (can_events => 0, @_); 2130 my $self = $class->SUPER::new (
2131 can_events => 0,
2132 @_,
2133 );
2105 2134
2106 $self->{image} or confess "Image has 'image' not set. This is a fatal error!"; 2135 $self->{path} || $self->{tex}
2136 or Carp::croak "'path' or 'tex' attributes required";
2107 2137
2108 $loaded_images{$self->{image}} ||= 2138 $self->{tex} ||= $texture_cache{$self->{path}} ||=
2109 new_from_file CFClient::Texture CFClient::find_rcfile $self->{image}, mipmap => 1; 2139 new_from_file CFClient::Texture CFClient::find_rcfile $self->{path}, mipmap => 1;
2110 2140
2111 my $tex = $self->{tex} = $loaded_images{$self->{image}}; 2141 Scalar::Util::weaken $texture_cache{$self->{path}};
2112 2142
2113 Scalar::Util::weaken $loaded_images{$self->{image}}; 2143 $self->{aspect} ||= $self->{tex}{w} / $self->{tex}{h};
2114
2115 $self->{aspect} = $tex->{w} / $tex->{h};
2116 2144
2117 $self 2145 $self
2118} 2146}
2119 2147
2120sub size_request { 2148sub size_request {
2121 my ($self) = @_; 2149 my ($self) = @_;
2122 2150
2123 ($self->{tex}->{w}, $self->{tex}->{h}) 2151 ($self->{tex}{w}, $self->{tex}{h})
2124} 2152}
2125 2153
2126sub _draw { 2154sub _draw {
2127 my ($self) = @_; 2155 my ($self) = @_;
2128 2156
2237 my $ycut1 = max 0, min 1, $ycut; 2265 my $ycut1 = max 0, min 1, $ycut;
2238 my $ycut2 = max 0, min 1, $ycut - 1; 2266 my $ycut2 = max 0, min 1, $ycut - 1;
2239 2267
2240 my $h1 = $self->{h} * (1 - $ycut1); 2268 my $h1 = $self->{h} * (1 - $ycut1);
2241 my $h2 = $self->{h} * (1 - $ycut2); 2269 my $h2 = $self->{h} * (1 - $ycut2);
2270 my $h3 = $self->{h};
2271
2272 $_ = $_ * (284-4)/288 + 4/288 for ($h1, $h2, $h3);
2242 2273
2243 glEnable GL_BLEND; 2274 glEnable GL_BLEND;
2244 glBlendFuncSeparate GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 2275 glBlendFuncSeparate GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
2245 GL_ONE, GL_ONE_MINUS_SRC_ALPHA; 2276 GL_ONE, GL_ONE_MINUS_SRC_ALPHA;
2246 glEnable GL_TEXTURE_2D; 2277 glEnable GL_TEXTURE_2D;
2265 2296
2266 if ($t3) { 2297 if ($t3) {
2267 glBindTexture GL_TEXTURE_2D, $t3->{name}; 2298 glBindTexture GL_TEXTURE_2D, $t3->{name};
2268 glBegin GL_QUADS; 2299 glBegin GL_QUADS;
2269 glTexCoord 0 , $t3->{t} * (1 - $ycut2); glVertex 0 , $h2; 2300 glTexCoord 0 , $t3->{t} * (1 - $ycut2); glVertex 0 , $h2;
2270 glTexCoord 0 , $t3->{t}; glVertex 0 , $self->{h}; 2301 glTexCoord 0 , $t3->{t}; glVertex 0 , $h3;
2271 glTexCoord $t3->{s}, $t3->{t}; glVertex $w, $self->{h}; 2302 glTexCoord $t3->{s}, $t3->{t}; glVertex $w, $h3;
2272 glTexCoord $t3->{s}, $t3->{t} * (1 - $ycut2); glVertex $w, $h2; 2303 glTexCoord $t3->{s}, $t3->{t} * (1 - $ycut2); glVertex $w, $h2;
2273 glEnd; 2304 glEnd;
2274 } 2305 }
2275 2306
2276 glDisable GL_BLEND; 2307 glDisable GL_BLEND;
2545 can_events => 0, 2576 can_events => 0,
2546 indent => 0, 2577 indent => 0,
2547 #font => default_font 2578 #font => default_font
2548 @_, 2579 @_,
2549 2580
2550 layout => (new CFClient::Layout 1), 2581 layout => (new CFClient::Layout),
2551 par => [], 2582 par => [],
2552 height => 0, 2583 height => 0,
2553 children => [ 2584 children => [
2554 (new CFClient::UI::Empty expand => 1), 2585 (new CFClient::UI::Empty expand => 1),
2555 (new CFClient::UI::Slider vertical => 1), 2586 (new CFClient::UI::Slider vertical => 1),
2566 2597
2567 $self->{fontsize} = $fontsize; 2598 $self->{fontsize} = $fontsize;
2568 $self->reflow; 2599 $self->reflow;
2569} 2600}
2570 2601
2602sub size_request {
2603 my ($self) = @_;
2604
2605 my ($empty, $slider) = @{ $self->{children} };
2606
2607 local $self->{children} = [$empty, $slider];
2608 $self->SUPER::size_request
2609}
2610
2571sub invoke_size_allocate { 2611sub invoke_size_allocate {
2572 my ($self, $w, $h) = @_; 2612 my ($self, $w, $h) = @_;
2573 2613
2614 my ($empty, $slider, @other) = @{ $self->{children} };
2615 $_->configure (@$_{qw(x y req_w req_h)}) for @other;
2616
2574 $self->{layout}->set_font ($self->{font}) if $self->{font}; 2617 $self->{layout}->set_font ($self->{font}) if $self->{font};
2575 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); 2618 $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE);
2576 $self->{layout}->set_width ($self->{children}[0]{w}); 2619 $self->{layout}->set_width ($empty->{w});
2577 $self->{layout}->set_indent ($self->{fontsize} * $::FONTSIZE * $self->{indent}); 2620 $self->{layout}->set_indent ($self->{fontsize} * $::FONTSIZE * $self->{indent});
2578 2621
2579 $self->reflow; 2622 $self->reflow;
2580 2623
2624 local $self->{children} = [$empty, $slider];
2581 $self->SUPER::invoke_size_allocate ($w, $h) 2625 $self->SUPER::invoke_size_allocate ($w, $h)
2582} 2626}
2583 2627
2584sub text_size { 2628sub get_layout {
2585 my ($self, $text, $indent) = @_; 2629 my ($self, $para) = @_;
2586 2630
2587 my $layout = $self->{layout}; 2631 my $layout = $self->{layout};
2588 2632
2633 $layout->set_font ($self->{font}) if $self->{font};
2634 $layout->set_foreground (@{$para->{fg}});
2589 $layout->set_height ($self->{fontsize} * $::FONTSIZE); 2635 $layout->set_height ($self->{fontsize} * $::FONTSIZE);
2590 $layout->set_width ($self->{children}[0]{w} - $indent); 2636 $layout->set_width ($self->{children}[0]{w} - $para->{indent});
2591 $layout->set_indent ($self->{fontsize} * $::FONTSIZE * $self->{indent}); 2637 $layout->set_indent ($self->{fontsize} * $::FONTSIZE * $self->{indent});
2592 $layout->set_markup ($text); 2638 $layout->set_markup ($para->{markup});
2639
2640 $layout->set_shapes (
2641 map
2642 +(0, $_->baseline_shift +$_->{padding_y} - $_->{h}, $_->{w}, $_->{h}),
2643 @{$para->{widget}}
2593 2644 );
2645
2594 $layout->size 2646 $layout
2595} 2647}
2596 2648
2597sub reflow { 2649sub reflow {
2598 my ($self) = @_; 2650 my ($self) = @_;
2599 2651
2608 $self->{children}[1]->set_value ($offset); 2660 $self->{children}[1]->set_value ($offset);
2609} 2661}
2610 2662
2611sub clear { 2663sub clear {
2612 my ($self) = @_; 2664 my ($self) = @_;
2665
2666 my (undef, undef, @other) = @{ $self->{children} };
2667 $self->remove ($_) for @other;
2613 2668
2614 $self->{par} = []; 2669 $self->{par} = [];
2615 $self->{height} = 0; 2670 $self->{height} = 0;
2616 $self->{children}[1]->set_range ([0, 0, 0, 1, 1]); 2671 $self->{children}[1]->set_range ([0, 0, 0, 1, 1]);
2617} 2672}
2618 2673
2619sub add_paragraph { 2674sub add_paragraph {
2620 my ($self, $color, $text, $indent) = @_; 2675 my ($self, $color, $para, $indent) = @_;
2621 2676
2622 for my $line (split /\n/, $text) { 2677 my ($text, @w) = ref $para ? @$para : $para;
2623 my ($w, $h) = $self->text_size ($line); 2678
2624 $self->{height} += $h; 2679 $para = {
2625 push @{$self->{par}}, [$w + $indent, $h, $color, $indent, $line]; 2680 w => 1e10,
2681 wrapped => 1,
2682 fg => $color,
2683 indent => $indent,
2684 markup => $text,
2685 widget => \@w,
2626 } 2686 };
2627 2687
2628 $self->{children}[1]->set_range ([$self->{height}, 0, $self->{height}, $self->{h}, 1]); 2688 $self->add (@w) if @w;
2689 push @{$self->{par}}, $para;
2690
2691 $self->{need_reflow}++;
2692 $self->update;
2693}
2694
2695sub scroll_to_bottom {
2696 my ($self) = @_;
2697
2698 $self->{scroll_to_bottom} = 1;
2699 $self->update;
2629} 2700}
2630 2701
2631sub update { 2702sub update {
2632 my ($self) = @_; 2703 my ($self) = @_;
2633 2704
2641 my ($W, $H) = @{$self->{children}[0]}{qw(w h)}; 2712 my ($W, $H) = @{$self->{children}[0]}{qw(w h)};
2642 2713
2643 if (delete $self->{need_reflow}) { 2714 if (delete $self->{need_reflow}) {
2644 my $height = 0; 2715 my $height = 0;
2645 2716
2646 my $layout = $self->{layout};
2647
2648 $layout->set_height ($self->{fontsize} * $::FONTSIZE);
2649
2650 for (@{$self->{par}}) { 2717 for my $para (@{$self->{par}}) {
2651 if (1 || $_->[0] >= $W) { # TODO: works,but needs reconfigure etc. support 2718 if ($para->{w} != $W && ($para->{wrapped} || $para->{w} > $W)) {
2652 $layout->set_width ($W - $_->[3]); 2719 my $layout = $self->get_layout ($para);
2653 $layout->set_indent ($self->{fontsize} * $::FONTSIZE * $self->{indent});
2654 $layout->set_markup ($_->[4]);
2655 my ($w, $h) = $layout->size; 2720 my ($w, $h) = $layout->size;
2656 $_->[0] = $w + $_->[3]; 2721
2657 $_->[1] = $h; 2722 $para->{w} = $w + $para->{indent};
2723 $para->{h} = $h;
2724 $para->{wrapped} = $layout->has_wrapped;
2658 } 2725 }
2659 2726
2660 $height += $_->[1]; 2727 $height += $para->{h};
2661 } 2728 }
2662 2729
2663 $self->{height} = $height; 2730 $self->{height} = $height;
2664 2731
2665 $self->{children}[1]->set_range ([$height, 0, $height, $H, 1]); 2732 $self->{children}[1]->set_range ([$self->{children}[1]{range}[0], 0, $height, $H, 1]);
2666 2733
2667 delete $self->{texture}; 2734 delete $self->{texture};
2735 }
2736
2737 if (delete $self->{scroll_to_bottom}) {
2738 $self->{children}[1]->set_value (1e10);
2668 } 2739 }
2669 2740
2670 $self->{texture} ||= new_from_opengl CFClient::Texture $W, $H, sub { 2741 $self->{texture} ||= new_from_opengl CFClient::Texture $W, $H, sub {
2671 glClearColor 0, 0, 0, 0; 2742 glClearColor 0, 0, 0, 0;
2672 glClear GL_COLOR_BUFFER_BIT; 2743 glClear GL_COLOR_BUFFER_BIT;
2676 my $y0 = $top; 2747 my $y0 = $top;
2677 my $y1 = $top + $H; 2748 my $y1 = $top + $H;
2678 2749
2679 my $y = 0; 2750 my $y = 0;
2680 2751
2681 my $layout = $self->{layout};
2682
2683 $layout->set_font ($self->{font}) if $self->{font};
2684
2685 glEnable GL_BLEND;
2686 #TODO# not correct in windows where rgba is forced off
2687 glBlendFunc GL_ONE, GL_ONE_MINUS_SRC_ALPHA;
2688
2689 for my $par (@{$self->{par}}) { 2752 for my $para (@{$self->{par}}) {
2690 my $h = $par->[1]; 2753 my $h = $para->{h};
2691 2754
2692 if ($y0 < $y + $h && $y < $y1) { 2755 if ($y0 < $y + $h && $y < $y1) {
2693 $layout->set_foreground (@{ $par->[2] });
2694 $layout->set_width ($W - $par->[3]);
2695 $layout->set_indent ($self->{fontsize} * $::FONTSIZE * $self->{indent});
2696 $layout->set_markup ($par->[4]);
2697 2756
2698 my ($w, $h, $data, $format, $internalformat) = $layout->render; 2757 my $layout = $self->get_layout ($para);
2699 2758
2700 glRasterPos $par->[3], $y - $y0; 2759 $layout->render ($para->{indent}, $y - $y0);
2701 glDrawPixels $w, $h, $format, GL_UNSIGNED_BYTE, $data; 2760
2761 if (my @w = @{ $para->{widget} }) {
2762 my @s = $layout->get_shapes;
2763
2764 for (@w) {
2765 my ($dx, $dy) = splice @s, 0, 2, ();
2766
2767 $_->{x} = $dx + $para->{indent};
2768 $_->{y} = $dy + $y - $y0;
2769
2770 $_->draw;
2771 }
2772 }
2702 } 2773 }
2703 2774
2704 $y += $h; 2775 $y += $h;
2705 } 2776 }
2706
2707 glDisable GL_BLEND;
2708 }; 2777 };
2709 }); 2778 });
2779}
2780
2781sub reconfigure {
2782 my ($self) = @_;
2783
2784 $self->SUPER::reconfigure;
2785
2786 $_->{w} = 1e10 for @{ $self->{par} };
2787 $self->reflow;
2710} 2788}
2711 2789
2712sub _draw { 2790sub _draw {
2713 my ($self) = @_; 2791 my ($self) = @_;
2714 2792
2717 glColor 0, 0, 0, 1; 2795 glColor 0, 0, 0, 1;
2718 $self->{texture}->draw_quad_alpha_premultiplied (0, 0, $self->{children}[0]{w}, $self->{children}[0]{h}); 2796 $self->{texture}->draw_quad_alpha_premultiplied (0, 0, $self->{children}[0]{w}, $self->{children}[0]{h});
2719 glDisable GL_TEXTURE_2D; 2797 glDisable GL_TEXTURE_2D;
2720 2798
2721 $self->{children}[1]->draw; 2799 $self->{children}[1]->draw;
2722
2723} 2800}
2724 2801
2725############################################################################# 2802#############################################################################
2726 2803
2727package CFClient::UI::Animator; 2804package CFClient::UI::Animator;
3000 for my $item (@{ $self->{items} }) { 3077 for my $item (@{ $self->{items} }) {
3001 my ($widget, $cb, $tooltip) = @$item; 3078 my ($widget, $cb, $tooltip) = @$item;
3002 3079
3003 # handle various types of items, only text for now 3080 # handle various types of items, only text for now
3004 if (!ref $widget) { 3081 if (!ref $widget) {
3082 if ($widget =~ /\t/) {
3083 my ($left, $right) = split /\t/, $widget, 2;
3084
3085 $widget = new CFClient::UI::HBox
3086 can_hover => 1,
3087 can_events => 1,
3088 tooltip => $tooltip,
3089 children => [
3090 (new CFClient::UI::Label markup => $left, expand => 1),
3091 (new CFClient::UI::Label markup => $right, align => +1),
3092 ],
3093 ;
3094
3095 } else {
3005 $widget = new CFClient::UI::Label 3096 $widget = new CFClient::UI::Label
3006 can_hover => 1, 3097 can_hover => 1,
3007 can_events => 1, 3098 can_events => 1,
3008 markup => $widget, 3099 markup => $widget,
3009 tooltip => $tooltip 3100 tooltip => $tooltip;
3101 }
3010 } 3102 }
3011 3103
3012 $self->{item}{$widget} = $item; 3104 $self->{item}{$widget} = $item;
3013 3105
3014 $self->{vbox}->add ($widget); 3106 $self->{vbox}->add ($widget);
3081 3173
3082 $self->SUPER::add (@widgets); 3174 $self->SUPER::add (@widgets);
3083 3175
3084 $self->{current} = $self->{children}[0] 3176 $self->{current} = $self->{children}[0]
3085 if @{ $self->{children} }; 3177 if @{ $self->{children} };
3178}
3179
3180sub get_current_page {
3181 my ($self) = @_;
3182
3183 $self->{current}
3086} 3184}
3087 3185
3088sub set_current_page { 3186sub set_current_page {
3089 my ($self, $page_or_widget) = @_; 3187 my ($self, $page_or_widget) = @_;
3090 3188
3156 tooltip => $tooltip, 3254 tooltip => $tooltip,
3157 on_activate => sub { $self->set_current_page ($widget) }, 3255 on_activate => sub { $self->set_current_page ($widget) },
3158 ); 3256 );
3159 3257
3160 $self->{multiplexer}->add ($widget); 3258 $self->{multiplexer}->add ($widget);
3259}
3260
3261sub get_current_page {
3262 my ($self) = @_;
3263
3264 $self->{multiplexer}->get_current_page
3161} 3265}
3162 3266
3163sub set_current_page { 3267sub set_current_page {
3164 my ($self, $page) = @_; 3268 my ($self, $page) = @_;
3165 3269
3343 count => 1, 3447 count => 1,
3344 %arg, 3448 %arg,
3345 }; 3449 };
3346 } 3450 }
3347 3451
3452 $ROOT->on_refresh (reorder => sub {
3348 $self->reorder; 3453 $self->reorder;
3454 });
3349} 3455}
3350 3456
3351sub reconfigure { 3457sub reconfigure {
3352 my ($self) = @_; 3458 my ($self) = @_;
3353 3459
3368 3474
3369############################################################################# 3475#############################################################################
3370 3476
3371package CFClient::UI::Inventory; 3477package CFClient::UI::Inventory;
3372 3478
3373our @ISA = CFClient::UI::ScrolledWindow::; 3479our @ISA = CFClient::UI::Table::;
3374 3480
3375sub new { 3481sub new {
3376 my $class = shift; 3482 my $class = shift;
3377 3483
3378 my $self = $class->SUPER::new ( 3484 my $self = $class->SUPER::new (
3379 child => (new CFClient::UI::Table col_expand => [0, 1, 0]), 3485 col_expand => [0, 1, 0],
3380 @_, 3486 @_,
3381 ); 3487 );
3382 3488
3383 $self 3489 $self
3384} 3490}
3385 3491
3386sub set_items { 3492sub set_items {
3387 my ($self, $items) = @_; 3493 my ($self, $items) = @_;
3388 3494
3389 $self->{child}->clear; 3495 $self->clear;
3390 return unless $items; 3496 return unless $items;
3391 3497
3392 my @items = sort { 3498 my @items = sort {
3393 ($a->{type} <=> $b->{type}) 3499 ($a->{type} <=> $b->{type})
3394 or ($a->{name} cmp $b->{name}) 3500 or ($a->{name} cmp $b->{name})
3395 } @$items; 3501 } values %$items;
3396 3502
3397 $self->{real_items} = \@items; 3503 $self->{real_items} = \@items;
3398 3504
3399 my $row = 0; 3505 my $row = 0;
3400 for my $item (@items) { 3506 for my $item (@items) {
3401 CFClient::Item::update_widgets $item; 3507 CFClient::Item::update_widgets $item;
3402 3508
3403 $self->{child}->add (0, $row, $item->{face_widget}); 3509 $self->add (0, $row, $item->{face_widget});
3404 $self->{child}->add (1, $row, $item->{desc_widget}); 3510 $self->add (1, $row, $item->{desc_widget});
3405 $self->{child}->add (2, $row, $item->{weight_widget}); 3511 $self->add (2, $row, $item->{weight_widget});
3406 3512
3407 $row++; 3513 $row++;
3408 }
3409}
3410
3411#############################################################################
3412
3413package CFClient::UI::BindEditor;
3414
3415our @ISA = CFClient::UI::FancyFrame::;
3416
3417sub new {
3418 my $class = shift;
3419
3420 my $self = $class->SUPER::new (binding => [], commands => [], @_);
3421
3422 $self->add (my $vb = new CFClient::UI::VBox);
3423
3424
3425 $vb->add ($self->{rec_btn} = new CFClient::UI::Button
3426 text => "start recording",
3427 tooltip => "Start/Stops recording of actions."
3428 ."All subsequent actions after the recording started will be captured."
3429 ."The actions are displayed after the record was stopped."
3430 ."To bind the action you have to click on the 'Bind' button",
3431 on_activate => sub {
3432 unless ($self->{recording}) {
3433 $self->start;
3434 } else {
3435 $self->stop;
3436 }
3437 });
3438
3439 $vb->add (new CFClient::UI::Label text => "Actions:");
3440 $vb->add ($self->{cmdbox} = new CFClient::UI::VBox);
3441
3442 $vb->add (new CFClient::UI::Label text => "Bound to: ");
3443 $vb->add (my $hb = new CFClient::UI::HBox);
3444 $hb->add ($self->{keylbl} = new CFClient::UI::Label expand => 1);
3445 $hb->add (new CFClient::UI::Button
3446 text => "bind",
3447 tooltip => "This opens a query where you have to press the key combination to bind the recorded actions",
3448 on_activate => sub {
3449 $self->ask_for_bind;
3450 });
3451
3452 $vb->add (my $hb = new CFClient::UI::HBox);
3453 $hb->add (new CFClient::UI::Button
3454 text => "ok",
3455 expand => 1,
3456 tooltip => "This closes the binding editor and saves the binding",
3457 on_activate => sub {
3458 $self->hide;
3459 $self->commit;
3460 });
3461
3462 $hb->add (new CFClient::UI::Button
3463 text => "cancel",
3464 expand => 1,
3465 tooltip => "This closes the binding editor without saving",
3466 on_activate => sub {
3467 $self->hide;
3468 $self->{binding_cancel}->()
3469 if $self->{binding_cancel};
3470 });
3471
3472 $self->update_binding_widgets;
3473
3474 $self
3475}
3476
3477sub cfg_bind {
3478 my ($self, $mod, $sym, $cmds) = @_;
3479 $::CFG->{profile}{default}{bindings}{$mod}{$sym} = $cmds;
3480 ::update_bindings ();
3481}
3482
3483sub cfg_unbind {
3484 my ($self, $mod, $sym, $cmds) = @_;
3485 delete $::CFG->{profile}{default}{bindings}{$mod}{$sym};
3486 ::update_bindings ();
3487}
3488
3489sub commit {
3490 my ($self) = @_;
3491 my ($mod, $sym, $cmds) = $self->get_binding;
3492 if ($sym != 0 && @$cmds > 0) {
3493 $::STATUSBOX->add ("Bound actions to '".CFClient::Binder::keycombo_to_name ($mod, $sym)
3494 ."'. Don't forget 'Save Config'!");
3495 $self->{binding_change}->($mod, $sym, $cmds)
3496 if $self->{binding_change};
3497 } else {
3498 $::STATUSBOX->add ("No action bound, no key or action specified!");
3499 $self->{binding_cancel}->()
3500 if $self->{binding_cancel};
3501 }
3502}
3503
3504sub start {
3505 my ($self) = @_;
3506
3507 $self->{rec_btn}->set_text ("stop recording");
3508 $self->{recording} = 1;
3509 $self->clear_command_list;
3510 $::CONN->start_record if $::CONN;
3511}
3512
3513sub stop {
3514 my ($self) = @_;
3515
3516 $self->{rec_btn}->set_text ("start recording");
3517 $self->{recording} = 0;
3518
3519 my $rec;
3520 $rec = $::CONN->stop_record if $::CONN;
3521 return unless ref $rec eq 'ARRAY';
3522 $self->set_command_list ($rec);
3523}
3524
3525
3526sub ask_for_bind_and_commit {
3527 my ($self) = @_;
3528 $self->ask_for_bind (1);
3529}
3530
3531sub ask_for_bind {
3532 my ($self, $commit, $end_cb) = @_;
3533
3534 CFClient::Binder::open_binding_dialog (sub {
3535 my ($mod, $sym) = @_;
3536 $self->{binding} = [$mod, $sym]; # XXX: how to stop that memleak?
3537 $self->update_binding_widgets;
3538 $self->commit if $commit;
3539 $end_cb->() if $end_cb;
3540 });
3541}
3542
3543# $mod and $sym are the modifiers and key symbol
3544# $cmds is a array ref of strings (the commands)
3545# $cb is the callback that is executed on OK
3546# $ccb is the callback that is executed on CANCEL and
3547# when the binding was unsuccessful on OK
3548sub set_binding {
3549 my ($self, $mod, $sym, $cmds, $cb, $ccb) = @_;
3550
3551 $self->clear_command_list;
3552 $self->{recording} = 0;
3553 $self->{rec_btn}->set_text ("start recording");
3554
3555 $self->{binding} = [$mod, $sym];
3556 $self->{commands} = $cmds;
3557
3558 $self->{binding_change} = $cb;
3559 $self->{binding_cancel} = $ccb;
3560
3561 $self->update_binding_widgets;
3562}
3563
3564# this is a shortcut method that asks for a binding
3565# and then just binds it.
3566sub do_quick_binding {
3567 my ($self, $cmds, $end_cb) = @_;
3568 $self->set_binding (undef, undef, $cmds, sub { $self->cfg_bind (@_) });
3569 $self->ask_for_bind (1, $end_cb);
3570}
3571
3572sub update_binding_widgets {
3573 my ($self) = @_;
3574 my ($mod, $sym, $cmds) = $self->get_binding;
3575 $self->{keylbl}->set_text (CFClient::Binder::keycombo_to_name ($mod, $sym));
3576 $self->set_command_list ($cmds);
3577}
3578
3579sub get_binding {
3580 my ($self) = @_;
3581 return (
3582 $self->{binding}->[0],
3583 $self->{binding}->[1],
3584 [ grep { defined $_ } @{$self->{commands}} ]
3585 );
3586}
3587
3588sub clear_command_list {
3589 my ($self) = @_;
3590 $self->{cmdbox}->clear ();
3591}
3592
3593sub set_command_list {
3594 my ($self, $cmds) = @_;
3595
3596 $self->{cmdbox}->clear ();
3597 $self->{commands} = $cmds;
3598
3599 my $idx = 0;
3600
3601 for (@$cmds) {
3602 $self->{cmdbox}->add (my $hb = new CFClient::UI::HBox);
3603
3604 my $i = $idx;
3605 $hb->add (new CFClient::UI::Label text => $_);
3606 $hb->add (new CFClient::UI::Button
3607 text => "delete",
3608 tooltip => "Deletes the action from the record",
3609 on_activate => sub {
3610 $self->{cmdbox}->remove ($hb);
3611 $cmds->[$i] = undef;
3612 });
3613
3614
3615 $idx++
3616 } 3514 }
3617} 3515}
3618 3516
3619############################################################################# 3517#############################################################################
3620 3518
3674 } elsif ($ev->{button} == 2) { 3572 } elsif ($ev->{button} == 2) {
3675 $::CONN->user_send ("invoke $spell->{name}"); 3573 $::CONN->user_send ("invoke $spell->{name}");
3676 } elsif ($ev->{button} == 3) { 3574 } elsif ($ev->{button} == 3) {
3677 (new CFClient::UI::Menu 3575 (new CFClient::UI::Menu
3678 items => [ 3576 items => [
3679 ["bind <i>cast $spell->{name}</i> to a key" => sub { $::BIND_EDITOR->do_quick_binding (["cast $spell->{name}"]) }], 3577 ["bind <i>cast $spell->{name}</i> to a key" => sub { $::BIND_EDITOR->do_quick_binding (["cast $spell->{name}"]) }],
3680 ["bind <i>invoke $spell->{name}</i> to a key" => sub { $::BIND_EDITOR->do_quick_binding (["invoke $spell->{name}"]) }], 3578 ["bind <i>invoke $spell->{name}</i> to a key" => sub { $::BIND_EDITOR->do_quick_binding (["invoke $spell->{name}"]) }],
3681 ], 3579 ],
3682 )->popup ($ev); 3580 )->popup ($ev);
3683 } else { 3581 } else {
3684 return 0; 3582 return 0;
3930 my ($w, $h) = @$widget{qw(alloc_w alloc_h)}; 3828 my ($w, $h) = @$widget{qw(alloc_w alloc_h)};
3931 3829
3932 $w = 0 if $w < 0; 3830 $w = 0 if $w < 0;
3933 $h = 0 if $h < 0; 3831 $h = 0 if $h < 0;
3934 3832
3833 $w = max $widget->{min_w}, $w;
3834 $h = max $widget->{min_h}, $h;
3835
3836 $w = min $widget->{max_w}, $w if exists $widget->{max_w};
3837 $h = min $widget->{max_h}, $h if exists $widget->{max_h};
3838
3935 $w = int $w + 0.5; 3839 $w = int $w + 0.5;
3936 $h = int $h + 0.5; 3840 $h = int $h + 0.5;
3937 3841
3938 if ($widget->{w} != $w || $widget->{h} != $h || delete $widget->{force_size_alloc}) { 3842 if ($widget->{w} != $w || $widget->{h} != $h || delete $widget->{force_size_alloc}) {
3939 $widget->{old_w} = $widget->{w}; 3843 $widget->{old_w} = $widget->{w};

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines