--- deliantra/Deliantra-Client/DC/UI.pm 2006/06/13 10:28:38 1.303 +++ deliantra/Deliantra-Client/DC/UI.pm 2006/06/24 00:24:09 1.313 @@ -283,8 +283,7 @@ $CFClient::UI::TOOLTIP_WATCHER->cb->() if $TOOLTIP->{owner} == $self; - $self->focus_out; - + $self->emit ("focus_out"); $self->emit (visibility_change => 0); } @@ -338,6 +337,10 @@ Carp::confess "size_request is abstract"; } +sub baseline_shift { + 0 +} + sub configure { my ($self, $x, $y, $w, $h) = @_; @@ -369,10 +372,6 @@ } } -sub size_allocate { - # nothing to be done -} - sub children { # nop } @@ -420,7 +419,7 @@ $self->{parent}->coord2global ($x + $self->{x}, $y + $self->{y}) } -sub focus_in { +sub invoke_focus_in { my ($self) = @_; return if $FOCUS == $self; @@ -428,38 +427,59 @@ my $focus = $FOCUS; $FOCUS = $self; - $self->_emit (focus_in => $focus); - $focus->update if $focus; $FOCUS->update; + + 0 } -sub focus_out { +sub invoke_focus_out { my ($self) = @_; return unless $FOCUS == $self; my $focus = $FOCUS; undef $FOCUS; - $self->_emit (focus_out => $focus); - $focus->update if $focus; #? - $::MAPWIDGET->focus_in #d# focus mapwidget if no other widget has focus + $::MAPWIDGET->grab_focus #d# focus mapwidget if no other widget has focus unless $FOCUS; + + 0 +} + +sub grab_focus { + my ($self) = @_; + + $self->emit ("focus_in"); } -sub mouse_motion { 0 } -sub button_up { 0 } -sub key_down { 0 } -sub key_up { 0 } +sub invoke_mouse_motion { 1 } +sub invoke_button_up { 1 } +sub invoke_key_down { 1 } +sub invoke_key_up { 1 } -sub button_down { +sub invoke_button_down { my ($self, $ev, $x, $y) = @_; - $self->focus_in; + $self->grab_focus; - 0 + 1 +} + +sub connect { + my ($self, $signal, $cb) = @_; + + push @{ $self->{signal_cb}{$signal} }, $cb; +} + +sub emit { + my ($self, $signal, @args) = @_; + + #d##TODO# stop propagating at first true, do not use sum + (List::Util::sum map $_->($self, @args), @{$self->{signal_cb}{$signal} || []}) # before + || ($self->can ("invoke_$signal") || sub { 1 })->($self, @args) # closure + || ($self->{parent} && $self->{parent}->emit ($signal, @args)) # parent } sub find_widget { @@ -481,29 +501,6 @@ $self->set_visible if $parent->{visible}; } -sub connect { - my ($self, $signal, $cb) = @_; - - push @{ $self->{signal_cb}{$signal} }, $cb; -} - -sub _emit { - my ($self, $signal, @args) = @_; - - List::Util::sum map $_->($self, @args), @{$self->{signal_cb}{$signal} || []} -} - -sub emit { - my ($self, $signal, @args) = @_; - - $self->_emit ($signal, @args) - || $self->$signal (@args); -} - -sub visibility_change { - #my ($self, $visible) = @_; -} - sub realloc { my ($self) = @_; @@ -544,8 +541,6 @@ # update screen rectangle local $draw_x = $draw_x + $self->{x}; local $draw_y = $draw_y + $self->{y}; - local $draw_w = $draw_x + $self->{w}; - local $draw_h = $draw_y + $self->{h}; # skip widgets that are entirely outside the drawing area return if ($draw_x + $self->{w} < 0) || ($draw_x >= $draw_w) @@ -791,10 +786,12 @@ $_[0]{children}[0]->size_request } -sub size_allocate { +sub invoke_size_allocate { my ($self, $w, $h) = @_; $self->{children}[0]->configure (0, 0, $w, $h); + + 1 } ############################################################################# @@ -820,11 +817,12 @@ $self->SUPER::update; } -sub size_allocate { +sub invoke_size_allocate { my ($self, $w, $h) = @_; - $self->SUPER::size_allocate ($w, $h); $self->update; + + $self->SUPER::invoke_size_allocate ($w, $h) } sub _render { @@ -895,7 +893,7 @@ ($w, $h) } -sub size_allocate { +sub invoke_size_allocate { my ($self, $w, $h) = @_; my $child = $self->child; @@ -905,6 +903,8 @@ $self->child->configure (0, 0, $w, $h); $self->update; + + 1 } sub set_offset { @@ -1004,13 +1004,13 @@ $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]); } -sub size_allocate { +sub invoke_size_allocate { my ($self, $w, $h) = @_; - $self->SUPER::size_allocate ($w, $h); - my $child = $self->{vp}->child; $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]); + + $self->SUPER::invoke_size_allocate ($w, $h) } #TODO# update range on size_allocate depending on child @@ -1092,13 +1092,13 @@ fontsize => $self->{border}, if exists $self->{title}; - unless ($self->{no_close_button}) { - $self->{close_btn} = + if ($self->{has_close_button}) { + $self->{close_button} = new CFClient::UI::ImageButton - image => 'x1_close.png', + path => 'x1_close.png', on_activate => sub { $self->hide }; - $self->CFClient::UI::Container::add ($self->{close_btn}); + $self->CFClient::UI::Container::add ($self->{close_button}); } $self @@ -1108,7 +1108,7 @@ my ($self, @widgets) = @_; $self->SUPER::add (@widgets); - $self->CFClient::UI::Container::add ($self->{close_btn}) if $self->{close_btn}; + $self->CFClient::UI::Container::add ($self->{close_button}) if $self->{close_button}; $self->CFClient::UI::Container::add ($self->{title_widget}) if $self->{title_widget}; } @@ -1122,8 +1122,8 @@ $self->{title_widget}->size_request if $self->{title_widget}; - $self->{close_btn}->size_request - if $self->{close_btn}; + $self->{close_button}->size_request + if $self->{close_button}; my ($w, $h) = $self->SUPER::size_request; @@ -1133,13 +1133,13 @@ ) } -sub size_allocate { +sub invoke_size_allocate { my ($self, $w, $h) = @_; if ($self->{title_widget}) { $self->{title_widget}{w} = $w; $self->{title_widget}{h} = $h; - $self->{title_widget}->size_allocate ($w, $h); + $self->{title_widget}->invoke_size_allocate ($w, $h); } my $border = $self->border; @@ -1149,11 +1149,13 @@ $self->child->configure ($border, $border, $w, $h); - $self->{close_btn}->configure ($self->{w} - (2 * $border), 0, $border, $border) - if $self->{close_btn}; + $self->{close_button}->configure ($self->{w} - $border, 0, $border, $border) + if $self->{close_button}; + + 1 } -sub button_down { +sub invoke_button_down { my ($self, $ev, $x, $y) = @_; my ($w, $h) = @$self{qw(w h)}; @@ -1194,7 +1196,7 @@ $self->move_abs ($bx + $x - $ox, $by + $y - $oy); # HACK: the next line is required to enforce placement - $self->{parent}->size_allocate ($self->{parent}{w}, $self->{parent}{h}); + $self->{parent}->invoke_size_allocate ($self->{parent}{w}, $self->{parent}{h}); }; } else { return 0; @@ -1203,21 +1205,18 @@ 1 } -sub button_up { +sub invoke_button_up { my ($self, $ev, $x, $y) = @_; - $self->{close_btn}->button_up ($ev, $x, $y) - if $self->{close_btn}; - - !!delete $self->{motion} + ! ! delete $self->{motion} } -sub mouse_motion { +sub invoke_mouse_motion { my ($self, $ev, $x, $y) = @_; $self->{motion}->($ev, $x, $y) if $self->{motion}; - !!$self->{motion} + ! ! $self->{motion} } sub _draw { @@ -1260,8 +1259,8 @@ glTranslate 0, - ($border - $self->{h}); } - $self->{close_btn}->draw - if $self->{close_btn}; + $self->{close_button}->draw + if $self->{close_button}; } ############################################################################# @@ -1350,7 +1349,7 @@ ) } -sub size_allocate { +sub invoke_size_allocate { my ($self, $w, $h) = @_; my ($ws, $hs) = $self->get_wh; @@ -1392,6 +1391,7 @@ $y += $row_h; } + 1 } sub find_widget { @@ -1438,39 +1438,39 @@ ) } -sub size_allocate { +sub invoke_size_allocate { my ($self, $w, $h) = @_; my $space = $self->{vertical} ? $h : $w; - my $children = $self->{children}; + my @children = $self->visible_children; my @req; if ($self->{homogeneous}) { - @req = ($space / (@$children || 1)) x @$children; + @req = ($space / (@children || 1)) x @children; } else { - @req = map $_->{$self->{vertical} ? "req_h" : "req_w"}, @$children; + @req = map $_->{$self->{vertical} ? "req_h" : "req_w"}, @children; my $req = List::Util::sum @req; if ($req > $space) { # ah well, not enough space $_ *= $space / $req for @req; } else { - my $expand = (List::Util::sum map $_->{expand}, @$children) || 1; + my $expand = (List::Util::sum map $_->{expand}, @children) || 1; $space = ($space - $req) / $expand; # remaining space to give away - $req[$_] += $space * $children->[$_]{expand} - for 0 .. $#$children; + $req[$_] += $space * $children[$_]{expand} + for 0 .. $#children; } } CFClient::UI::harmonize \@req; my $pos = 0; - for (0 .. $#$children) { + for (0 .. $#children) { my $alloc = $req[$_]; - $children->[$_]->configure ($self->{vertical} ? (0, $pos, $w, $alloc) : ($pos, 0, $alloc, $h)); + $children[$_]->configure ($self->{vertical} ? (0, $pos, $w, $alloc) : ($pos, 0, $alloc, $h)); $pos += $alloc; } @@ -1635,13 +1635,19 @@ @{ $self->{size_req} } } -sub size_allocate { +sub baseline_shift { + $_[0]{layout}->descent +} + +sub invoke_size_allocate { my ($self, $w, $h) = @_; delete $self->{ox}; delete $self->{texture} unless $w >= $self->{req_w} && $self->{old_w} >= $self->{req_w}; + + 1 } sub set_fontsize { @@ -1744,7 +1750,7 @@ $self->{layout}->set_text ("$text "); delete $self->{size_req}; - $self->_emit (changed => $self->{text}); + $self->emit (changed => $self->{text}); $self->realloc; $self->update; @@ -1769,7 +1775,7 @@ ($w + 1, $h) # add 1 for cursor } -sub key_down { +sub invoke_key_down { my ($self, $ev) = @_; my $mod = $ev->{mod}; @@ -1791,7 +1797,7 @@ } elsif ($sym == CFClient::SDLK_END) { $self->{cursor} = length $text; } elsif ($uni == 27) { - $self->_emit ('escape'); + $self->emit ('escape'); } elsif ($uni) { substr $text, $self->{cursor}++, 0, chr $uni; } else { @@ -1805,18 +1811,18 @@ 1 } -sub focus_in { +sub invoke_focus_in { my ($self) = @_; $self->{last_activity} = $::NOW; - $self->SUPER::focus_in; + $self->SUPER::invoke_focus_in } -sub button_down { +sub invoke_button_down { my ($self, $ev, $x, $y) = @_; - $self->SUPER::button_down ($ev, $x, $y); + $self->SUPER::invoke_button_down ($ev, $x, $y); my $idx = $self->{layout}->xy_to_index ($x, $y); @@ -1831,11 +1837,11 @@ 1 } -sub mouse_motion { +sub invoke_mouse_motion { my ($self, $ev, $x, $y) = @_; # printf "M %d,%d %d,%d\n", $ev->motion_x, $ev->motion_y, $x, $y;#d# - 0 + 1 } sub _draw { @@ -1886,7 +1892,7 @@ use CFClient::OpenGL; -sub key_down { +sub invoke_key_down { my ($self, $ev) = @_; my $sym = $ev->{sym}; @@ -1894,9 +1900,10 @@ if ($sym == 13) { unshift @{$self->{history}}, my $txt = $self->get_text; + $self->{history_pointer} = -1; $self->{history_saveback} = ''; - $self->_emit (activate => $txt); + $self->emit (activate => $txt); $self->update; } elsif ($sym == CFClient::SDLK_UP) { @@ -1922,7 +1929,7 @@ } } else { - return $self->SUPER::key_down ($ev) + return $self->SUPER::invoke_key_down ($ev) } 1 @@ -1956,9 +1963,7 @@ ) } -sub activate { } - -sub button_up { +sub invoke_button_up { my ($self, $ev, $x, $y) = @_; $self->emit ("activate") @@ -2010,9 +2015,7 @@ ); } -sub activate { } - -sub button_up { +sub invoke_button_up { my ($self, $ev, $x, $y) = @_; $self->emit ("activate") @@ -2056,13 +2059,13 @@ (6) x 2 } -sub button_down { +sub invoke_button_down { my ($self, $ev, $x, $y) = @_; if ($x >= $self->{padding_x} && $x < $self->{w} - $self->{padding_x} && $y >= $self->{padding_y} && $y < $self->{h} - $self->{padding_y}) { $self->{state} = !$self->{state}; - $self->_emit (changed => $self->{state}); + $self->emit (changed => $self->{state}); } else { return 0 } @@ -2097,25 +2100,26 @@ our @ISA = CFClient::UI::Base::; use CFClient::OpenGL; -use Carp qw/confess/; -our %loaded_images; +our %texture_cache; sub new { my $class = shift; - my $self = $class->SUPER::new (can_events => 0, @_); - - $self->{image} or confess "Image has 'image' not set. This is a fatal error!"; + my $self = $class->SUPER::new ( + can_events => 0, + @_, + ); - $loaded_images{$self->{image}} ||= - new_from_file CFClient::Texture CFClient::find_rcfile $self->{image}, mipmap => 1; + $self->{path} + or Carp::croak "required attribute 'path' not set"; - my $tex = $self->{tex} = $loaded_images{$self->{image}}; + $self->{tex} = $texture_cache{$self->{path}} ||= + new_from_file CFClient::Texture CFClient::find_rcfile $self->{path}, mipmap => 1; - Scalar::Util::weaken $loaded_images{$self->{image}}; + Scalar::Util::weaken $texture_cache{$self->{path}}; - $self->{aspect} = $tex->{w} / $tex->{h}; + $self->{aspect} ||= $self->{tex}{w} / $self->{tex}{h}; $self } @@ -2123,7 +2127,7 @@ sub size_request { my ($self) = @_; - ($self->{tex}->{w}, $self->{tex}->{h}) + ($self->{tex}{w}, $self->{tex}{h}) } sub _draw { @@ -2369,8 +2373,6 @@ $self } -sub changed { } - sub set_range { my ($self, $range) = @_; @@ -2400,7 +2402,7 @@ @{$self->{range}} = ($value, $lo, $hi, $page, $unit); if ($value != $old_value) { - $self->_emit (changed => $value); + $self->emit (changed => $value); $self->update; } } @@ -2411,17 +2413,17 @@ ($self->{req_w}, $self->{req_h}) } -sub button_down { +sub invoke_button_down { my ($self, $ev, $x, $y) = @_; - $self->SUPER::button_down ($ev, $x, $y); + $self->SUPER::invoke_button_down ($ev, $x, $y); $self->{click} = [$self->{range}[0], $self->{vertical} ? $y : $x]; - $self->mouse_motion ($ev, $x, $y) + $self->invoke_mouse_motion ($ev, $x, $y) } -sub mouse_motion { +sub invoke_mouse_motion { my ($self, $ev, $x, $y) = @_; if ($GRAB == $self) { @@ -2573,30 +2575,51 @@ $self->reflow; } -sub size_allocate { +sub size_request { + my ($self) = @_; + + my ($empty, $slider) = @{ $self->{children} }; + + local $self->{children} = [$empty, $slider]; + $self->SUPER::size_request +} + +sub invoke_size_allocate { my ($self, $w, $h) = @_; - $self->SUPER::size_allocate ($w, $h); + my ($empty, $slider, @other) = @{ $self->{children} }; + $_->configure (@$_{qw(x y req_w req_h)}) for @other; $self->{layout}->set_font ($self->{font}) if $self->{font}; $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); - $self->{layout}->set_width ($self->{children}[0]{w}); + $self->{layout}->set_width ($empty->{w}); $self->{layout}->set_indent ($self->{fontsize} * $::FONTSIZE * $self->{indent}); $self->reflow; + + local $self->{children} = [$empty, $slider]; + $self->SUPER::invoke_size_allocate ($w, $h) } -sub text_size { - my ($self, $text, $indent) = @_; +sub get_layout { + my ($self, $para) = @_; my $layout = $self->{layout}; + $layout->set_font ($self->{font}) if $self->{font}; + $layout->set_foreground (@{$para->{fg}}); $layout->set_height ($self->{fontsize} * $::FONTSIZE); - $layout->set_width ($self->{children}[0]{w} - $indent); + $layout->set_width ($self->{children}[0]{w} - $para->{indent}); $layout->set_indent ($self->{fontsize} * $::FONTSIZE * $self->{indent}); - $layout->set_markup ($text); - - $layout->size + $layout->set_markup ($para->{markup}); + + $layout->set_shapes ( + map + +(0, $_->baseline_shift +$_->{padding_y} - $_->{h}, $_->{w}, $_->{h}), + @{$para->{widget}} + ); + + $layout } sub reflow { @@ -2616,21 +2639,40 @@ sub clear { my ($self) = @_; + my (undef, undef, @other) = @{ $self->{children} }; + $self->remove ($_) for @other; + $self->{par} = []; $self->{height} = 0; $self->{children}[1]->set_range ([0, 0, 0, 1, 1]); } sub add_paragraph { - my ($self, $color, $text, $indent) = @_; + my ($self, $color, $para, $indent) = @_; - for my $line (split /\n/, $text) { - my ($w, $h) = $self->text_size ($line); - $self->{height} += $h; - push @{$self->{par}}, [$w + $indent, $h, $color, $indent, $line]; - } + my ($text, @w) = ref $para ? @$para : $para; + + $para = { + w => 1e10, + wrapped => 1, + fg => $color, + indent => $indent, + markup => $text, + widget => \@w, + }; + + $self->add (@w) if @w; + push @{$self->{par}}, $para; + + $self->{need_reflow}++; + $self->update; +} + +sub scroll_to_bottom { + my ($self) = @_; - $self->{children}[1]->set_range ([$self->{height}, 0, $self->{height}, $self->{h}, 1]); + $self->{scroll_to_bottom} = 1; + $self->update; } sub update { @@ -2648,30 +2690,30 @@ if (delete $self->{need_reflow}) { my $height = 0; - my $layout = $self->{layout}; - - $layout->set_height ($self->{fontsize} * $::FONTSIZE); - - for (@{$self->{par}}) { - if (1 || $_->[0] >= $W) { # TODO: works,but needs reconfigure etc. support - $layout->set_width ($W - $_->[3]); - $layout->set_indent ($self->{fontsize} * $::FONTSIZE * $self->{indent}); - $layout->set_markup ($_->[4]); + for my $para (@{$self->{par}}) { + if ($para->{w} != $W && ($para->{wrapped} || $para->{w} > $W)) { + my $layout = $self->get_layout ($para); my ($w, $h) = $layout->size; - $_->[0] = $w + $_->[3]; - $_->[1] = $h; + + $para->{w} = $w + $para->{indent}; + $para->{h} = $h; + $para->{wrapped} = $layout->has_wrapped; } - $height += $_->[1]; + $height += $para->{h}; } $self->{height} = $height; - $self->{children}[1]->set_range ([$height, 0, $height, $H, 1]); + $self->{children}[1]->set_range ([$self->{children}[1]{range}[0], 0, $height, $H, 1]); delete $self->{texture}; } + if (delete $self->{scroll_to_bottom}) { + $self->{children}[1]->set_value (1e10); + } + $self->{texture} ||= new_from_opengl CFClient::Texture $W, $H, sub { glClearColor 0, 0, 0, 0; glClear GL_COLOR_BUFFER_BIT; @@ -2683,27 +2725,37 @@ my $y = 0; - my $layout = $self->{layout}; - - $layout->set_font ($self->{font}) if $self->{font}; - glEnable GL_BLEND; #TODO# not correct in windows where rgba is forced off glBlendFunc GL_ONE, GL_ONE_MINUS_SRC_ALPHA; - for my $par (@{$self->{par}}) { - my $h = $par->[1]; + for my $para (@{$self->{par}}) { + my $h = $para->{h}; if ($y0 < $y + $h && $y < $y1) { - $layout->set_foreground (@{ $par->[2] }); - $layout->set_width ($W - $par->[3]); - $layout->set_indent ($self->{fontsize} * $::FONTSIZE * $self->{indent}); - $layout->set_markup ($par->[4]); + + my $layout = $self->get_layout ($para); my ($w, $h, $data, $format, $internalformat) = $layout->render; - glRasterPos $par->[3], $y - $y0; + glRasterPos $para->{indent}, $y - $y0; glDrawPixels $w, $h, $format, GL_UNSIGNED_BYTE, $data; + + if (my @w = @{ $para->{widget} }) { + my @s = $layout->get_shapes; + + glDisable GL_BLEND; + for (@w) { + my ($dx, $dy) = splice @s, 0, 2, (); + + $_->{x} = $dx + $para->{indent}; + $_->{y} = $dy + $y - $y0; + + $_->draw; + } + glEnable GL_BLEND; + glBlendFunc GL_ONE, GL_ONE_MINUS_SRC_ALPHA; + } } $y += $h; @@ -2714,6 +2766,15 @@ }); } +sub reconfigure { + my ($self) = @_; + + $self->SUPER::reconfigure; + + $_->{w} = 1e10 for @{ $self->{par} }; + $self->reflow; +} + sub _draw { my ($self) = @_; @@ -2724,7 +2785,6 @@ glDisable GL_TEXTURE_2D; $self->{children}[1]->draw; - } ############################################################################# @@ -2843,13 +2903,13 @@ ($w + 4, $h + 4) } -sub size_allocate { +sub invoke_size_allocate { my ($self, $w, $h) = @_; - $self->SUPER::size_allocate ($w - 4, $h - 4); + $self->SUPER::invoke_size_allocate ($w - 4, $h - 4) } -sub visibility_change { +sub invoke_visibility_change { my ($self, $visible) = @_; return unless $visible; @@ -3026,7 +3086,7 @@ sub popup { my ($self, $ev) = @_; - $self->_emit ("popdown"); + $self->emit ("popdown"); # maybe save $GRAB? must be careful about events... $GRAB = $self; @@ -3036,7 +3096,7 @@ $self->move_abs ($ev->{x} - $self->{w} * 0.5, $ev->{y} - $self->{h} * 0.5); } -sub mouse_motion { +sub invoke_mouse_motion { my ($self, $ev, $x, $y) = @_; # TODO: should use vbox->find_widget or so @@ -3046,14 +3106,14 @@ 0 } -sub button_up { +sub invoke_button_up { my ($self, $ev, $x, $y) = @_; if ($ev->{button} == $self->{button}) { undef $GRAB; $self->hide; - $self->_emit ("popdown"); + $self->emit ("popdown"); $self->{hover}[1]->() if $self->{hover}; } else { return 0 @@ -3100,7 +3160,7 @@ $self->{current} = $widget; $self->{current}->configure (0, 0, $self->{w}, $self->{h}); - $self->_emit (page_changed => $self->{current}); + $self->emit (page_changed => $self->{current}); $self->realloc; } @@ -3115,10 +3175,12 @@ $self->{current}->size_request } -sub size_allocate { +sub invoke_size_allocate { my ($self, $w, $h) = @_; $self->{current}->configure (0, 0, $w, $h); + + 1 } sub _draw { @@ -3167,7 +3229,7 @@ my ($self, $page) = @_; $self->{multiplexer}->set_current_page ($page); - $self->_emit (page_changed => $self->{multiplexer}{current}); + $self->emit (page_changed => $self->{multiplexer}{current}); } ############################################################################# @@ -3192,7 +3254,7 @@ $self } -sub button_down { +sub invoke_button_down { my ($self, $ev) = @_; my @menu_items; @@ -3223,7 +3285,7 @@ return unless $self->{value} ne $value; $self->_set_value ($value); - $self->_emit (changed => $value); + $self->emit (changed => $value); } ############################################################################# @@ -3477,6 +3539,18 @@ $self } +sub cfg_bind { + my ($self, $mod, $sym, $cmds) = @_; + $::CFG->{profile}{default}{bindings}{$mod}{$sym} = $cmds; + ::update_bindings (); +} + +sub cfg_unbind { + my ($self, $mod, $sym, $cmds) = @_; + delete $::CFG->{profile}{default}{bindings}{$mod}{$sym}; + ::update_bindings (); +} + sub commit { my ($self) = @_; my ($mod, $sym, $cmds) = $self->get_binding; @@ -3520,13 +3594,14 @@ } sub ask_for_bind { - my ($self, $commit) = @_; + my ($self, $commit, $end_cb) = @_; CFClient::Binder::open_binding_dialog (sub { my ($mod, $sym) = @_; $self->{binding} = [$mod, $sym]; # XXX: how to stop that memleak? $self->update_binding_widgets; $self->commit if $commit; + $end_cb->() if $end_cb; }); } @@ -3554,11 +3629,9 @@ # this is a shortcut method that asks for a binding # and then just binds it. sub do_quick_binding { - my ($self, $cmds) = @_; - $self->set_binding (undef, undef, $cmds, sub { - $::CFG->{bindings}->{$_[0]}->{$_[1]} = $_[2]; - }); - $self->ask_for_bind (1); + my ($self, $cmds, $end_cb) = @_; + $self->set_binding (undef, undef, $cmds, sub { $self->cfg_bind (@_) }); + $self->ask_for_bind (1, $end_cb); } sub update_binding_widgets { @@ -3773,7 +3846,7 @@ int $coord + 0.5 } -sub size_allocate { +sub invoke_size_allocate { my ($self, $w, $h) = @_; for my $child ($self->children) { @@ -3787,6 +3860,8 @@ $child->configure ($X, $Y, $W, $H); } + + 1 } sub coord2local {