--- deliantra/Deliantra-Client/DC/BindingEditor.pm 2006/06/26 21:59:04 1.1 +++ deliantra/Deliantra-Client/DC/BindingEditor.pm 2006/07/30 13:16:44 1.4 @@ -1,8 +1,65 @@ -package CFClient::BindingEditor; +package CFPlus::BindingEditor; -use CFClient::UI; +use strict; -our @ISA = CFClient::UI::FancyFrame::; +use CFPlus::UI; + +our @ISA = CFPlus::UI::FancyFrame::; + +my @ALLOWED_MODIFIER_KEYS = ( + CFPlus::SDLK_LSHIFT, + CFPlus::SDLK_LCTRL , + CFPlus::SDLK_LALT , + CFPlus::SDLK_LMETA , + + CFPlus::SDLK_RSHIFT, + CFPlus::SDLK_RCTRL , + CFPlus::SDLK_RALT , + CFPlus::SDLK_RMETA , +); + +my %ALLOWED_MODIFIERS = ( + CFPlus::KMOD_LSHIFT => "LSHIFT", + CFPlus::KMOD_LCTRL => "LCTRL", + CFPlus::KMOD_LALT => "LALT", + CFPlus::KMOD_LMETA => "LMETA", + + CFPlus::KMOD_RSHIFT => "RSHIFT", + CFPlus::KMOD_RCTRL => "RCTRL", + CFPlus::KMOD_RALT => "RALT", + CFPlus::KMOD_RMETA => "RMETA", +); + +my %DIRECT_BIND_CHARS = map { $_ => 1 } qw/0 1 2 3 4 5 6 7 8 9/; +my @DIRECT_BIND_KEYS = ( + CFPlus::SDLK_F1, + CFPlus::SDLK_F2, + CFPlus::SDLK_F3, + CFPlus::SDLK_F4, + CFPlus::SDLK_F5, + CFPlus::SDLK_F6, + CFPlus::SDLK_F7, + CFPlus::SDLK_F8, + CFPlus::SDLK_F9, + CFPlus::SDLK_F10, + CFPlus::SDLK_F11, + CFPlus::SDLK_F12, + CFPlus::SDLK_F13, + CFPlus::SDLK_F14, + CFPlus::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 . CFPlus::SDL_GetKeyName ($sym); +} sub new { my $class = shift; @@ -14,9 +71,9 @@ @_ ); - $self->add (my $vb = new CFClient::UI::VBox); + $self->add (my $vb = new CFPlus::UI::VBox); - $vb->add ($self->{rec_btn} = new CFClient::UI::Button + $vb->add ($self->{rec_btn} = new CFPlus::UI::Button text => "start recording", tooltip => "Start/Stops recording of actions." ."All subsequent actions after the recording started will be captured." @@ -30,37 +87,41 @@ } }); - $vb->add (new CFClient::UI::Label text => "Actions:"); - $vb->add ($self->{cmdbox} = new CFClient::UI::VBox); + $vb->add (new CFPlus::UI::Label text => "Actions:"); + $vb->add ($self->{cmdbox} = new CFPlus::UI::VBox); - $vb->add (new CFClient::UI::Label text => "Bound to: "); - $vb->add (my $hb = new CFClient::UI::HBox); - $hb->add ($self->{keylbl} = new CFClient::UI::Label expand => 1); - $hb->add (new CFClient::UI::Button + $vb->add (new CFPlus::UI::Label text => "Bound to: "); + $vb->add (my $hb = new CFPlus::UI::HBox); + $hb->add ($self->{keylbl} = new CFPlus::UI::Label expand => 1); + $hb->add (new CFPlus::UI::Button text => "bind", tooltip => "This opens a query where you have to press the key combination to bind the recorded actions", on_activate => sub { $self->ask_for_bind; }); - $vb->add (my $hb = new CFClient::UI::HBox); - $hb->add (new CFClient::UI::Button - text => "ok", + $vb->add (my $hb = new CFPlus::UI::HBox); + $hb->add (new CFPlus::UI::Button + 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", + $hb->add (new CFPlus::UI::Button + 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,71 @@ $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 CFPlus::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 CFPlus::UI::VBox); + $vb->add (new CFPlus::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 CFPlus::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 == CFPlus::KMOD_NONE + and not $DIRECT_BIND_CHARS{chr ($ev->{unicode})} + and not grep { $sym == $_ } @DIRECT_BIND_KEYS) + { + $::STATUSBOX->add ( + "Cannot bind key " . CFPlus::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; + + (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 +278,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); } @@ -193,11 +305,11 @@ my $idx = 0; for (@$cmds) { - $self->{cmdbox}->add (my $hb = new CFClient::UI::HBox); + $self->{cmdbox}->add (my $hb = new CFPlus::UI::HBox); my $i = $idx; - $hb->add (new CFClient::UI::Label text => $_); - $hb->add (new CFClient::UI::Button + $hb->add (new CFPlus::UI::Label text => $_); + $hb->add (new CFPlus::UI::Button text => "delete", tooltip => "Deletes the action from the record", on_activate => sub {