--- deliantra/Deliantra-Client/DC/BindingEditor.pm 2006/06/26 21:59:04 1.1 +++ deliantra/Deliantra-Client/DC/BindingEditor.pm 2006/07/02 18:52:05 1.2 @@ -1,9 +1,66 @@ package CFClient::BindingEditor; +use strict; + use CFClient::UI; our @ISA = CFClient::UI::FancyFrame::; +my @ALLOWED_MODIFIER_KEYS = ( + CFClient::SDLK_LSHIFT, + CFClient::SDLK_LCTRL , + CFClient::SDLK_LALT , + CFClient::SDLK_LMETA , + + CFClient::SDLK_RSHIFT, + CFClient::SDLK_RCTRL , + CFClient::SDLK_RALT , + CFClient::SDLK_RMETA , +); + +my %ALLOWED_MODIFIERS = ( + CFClient::KMOD_LSHIFT => "LSHIFT", + CFClient::KMOD_LCTRL => "LCTRL", + CFClient::KMOD_LALT => "LALT", + CFClient::KMOD_LMETA => "LMETA", + + CFClient::KMOD_RSHIFT => "RSHIFT", + CFClient::KMOD_RCTRL => "RCTRL", + CFClient::KMOD_RALT => "RALT", + CFClient::KMOD_RMETA => "RMETA", +); + +my %DIRECT_BIND_CHARS = map { $_ => 1 } qw/0 1 2 3 4 5 6 7 8 9/; +my @DIRECT_BIND_KEYS = ( + CFClient::SDLK_F1, + CFClient::SDLK_F2, + CFClient::SDLK_F3, + CFClient::SDLK_F4, + CFClient::SDLK_F5, + CFClient::SDLK_F6, + CFClient::SDLK_F7, + CFClient::SDLK_F8, + CFClient::SDLK_F9, + CFClient::SDLK_F10, + CFClient::SDLK_F11, + CFClient::SDLK_F12, + CFClient::SDLK_F13, + CFClient::SDLK_F14, + CFClient::SDLK_F15, +); + +sub keycombo_to_name { + my ($mod, $sym) = @_; + + my $mods = join '+', + map { $ALLOWED_MODIFIERS{$_} } + grep { ($_ + 0) & ($mod + 0) } + keys %ALLOWED_MODIFIERS; + $mods .= "+" if $mods ne ''; + + return $mods . CFClient::SDL_GetKeyName ($sym); +} + sub new { my $class = shift; @@ -45,22 +102,26 @@ $vb->add (my $hb = new CFClient::UI::HBox); $hb->add (new CFClient::UI::Button - text => "ok", + text => "OK", expand => 1, tooltip => "This closes the binding editor and saves the binding", on_activate => sub { + (delete $self->{binder})->destroy if $self->{binder}; $self->hide; $self->commit; + 0 }); $hb->add (new CFClient::UI::Button - text => "cancel", + text => "Cancel", expand => 1, tooltip => "This closes the binding editor without saving", on_activate => sub { + (delete $self->{binder})->destroy if $self->{binder}; $self->hide; $self->{binding_cancel}->() if $self->{binding_cancel}; + 0 }); $self->update_binding_widgets; @@ -82,10 +143,12 @@ sub commit { my ($self) = @_; + my ($mod, $sym, $cmds) = $self->get_binding; + if ($sym != 0 && @$cmds > 0) { - $::STATUSBOX->add ("Bound actions to '".CFClient::Binder::keycombo_to_name ($mod, $sym) - ."'. Don't forget 'Save Config'!"); + $::STATUSBOX->add ("Bound actions to " . keycombo_to_name ($mod, $sym) . ". " + . "Do not forget to 'Save Config'!"); $self->{binding_change}->($mod, $sym, $cmds) if $self->{binding_change}; } else { @@ -116,22 +179,72 @@ $self->set_command_list ($rec); } - -sub ask_for_bind_and_commit { - my ($self) = @_; - $self->ask_for_bind (1); -} - sub ask_for_bind { 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; - }); + return if $self->{binder}; + + Scalar::Util::weaken $self; + + $self->{binder} = new CFClient::UI::FancyFrame + title => "Bind Action", + x => "center", + y => "center", + z => 1000, + has_close_button => 1, + on_delete => sub { + (delete $self->{binder})->destroy; + 1 + }, + ; + + $self->{binder}->add (my $vb = new CFClient::UI::VBox); + $vb->add (new CFClient::UI::Label + text => "Press a modifier (CTRL, ALT and/or SHIFT) and a key." + . "You can only bind 0-9 and F1-F15 without modifiers." + ); + $vb->add (my $entry = new CFClient::UI::Entry + text => "", + on_key_down => sub { + my ($entry, $ev) = @_; + + my $mod = $ev->{mod}; + my $sym = $ev->{sym}; + + # XXX: This seems a little bit hackisch to me, but I have to ignore them + return if grep { $_ == $sym } @ALLOWED_MODIFIER_KEYS; + + if ($mod == CFClient::KMOD_NONE + and not $DIRECT_BIND_CHARS{chr ($ev->{unicode})} + and not grep { $sym == $_ } @DIRECT_BIND_KEYS) + { + $::STATUSBOX->add ( + "Cannot bind key " . CFClient::SDL_GetKeyName ($sym) . " directly without modifier, " + . "as those keys are reserved for the command completer." + ); + return; + } + + $entry->grab_focus; + + $self->{binding} = [$mod, $sym]; + $self->update_binding_widgets; + $self->commit if $commit; + $end_cb->() if $end_cb; + + warn "dexxey $self $self->{binder}\n";#d# + (delete $self->{binder})->destroy; + 1 + }, + on_focus_out => sub { + # segfaults and worse :() + #(delete $self->{binder})->destroy if $self->{binder}; + 1 + }, + ); + + $entry->grab_focus; + $self->{binder}->show; } # $mod and $sym are the modifiers and key symbol @@ -166,7 +279,7 @@ sub update_binding_widgets { my ($self) = @_; my ($mod, $sym, $cmds) = $self->get_binding; - $self->{keylbl}->set_text (CFClient::Binder::keycombo_to_name ($mod, $sym)); + $self->{keylbl}->set_text (keycombo_to_name ($mod, $sym)); $self->set_command_list ($cmds); }