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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines