package CFClient::BindingEditor; use CFClient::UI; our @ISA = CFClient::UI::FancyFrame::; sub new { my $class = shift; my $self = $class->SUPER::new ( binding => [], commands => [], title => "Macro/Keybinding Recorder", @_ ); $self->add (my $vb = new CFClient::UI::VBox); $vb->add ($self->{rec_btn} = new CFClient::UI::Button text => "start recording", tooltip => "Start/Stops recording of actions." ."All subsequent actions after the recording started will be captured." ."The actions are displayed after the record was stopped." ."To bind the action you have to click on the 'Bind' button", on_activate => sub { unless ($self->{recording}) { $self->start; } else { $self->stop; } }); $vb->add (new CFClient::UI::Label text => "Actions:"); $vb->add ($self->{cmdbox} = new CFClient::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 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", expand => 1, tooltip => "This closes the binding editor and saves the binding", on_activate => sub { $self->hide; $self->commit; }); $hb->add (new CFClient::UI::Button text => "cancel", expand => 1, tooltip => "This closes the binding editor without saving", on_activate => sub { $self->hide; $self->{binding_cancel}->() if $self->{binding_cancel}; }); $self->update_binding_widgets; $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; if ($sym != 0 && @$cmds > 0) { $::STATUSBOX->add ("Bound actions to '".CFClient::Binder::keycombo_to_name ($mod, $sym) ."'. Don't forget 'Save Config'!"); $self->{binding_change}->($mod, $sym, $cmds) if $self->{binding_change}; } else { $::STATUSBOX->add ("No action bound, no key or action specified!"); $self->{binding_cancel}->() if $self->{binding_cancel}; } } sub start { my ($self) = @_; $self->{rec_btn}->set_text ("stop recording"); $self->{recording} = 1; $self->clear_command_list; $::CONN->start_record if $::CONN; } sub stop { my ($self) = @_; $self->{rec_btn}->set_text ("start recording"); $self->{recording} = 0; my $rec; $rec = $::CONN->stop_record if $::CONN; return unless ref $rec eq 'ARRAY'; $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; }); } # $mod and $sym are the modifiers and key symbol # $cmds is a array ref of strings (the commands) # $cb is the callback that is executed on OK # $ccb is the callback that is executed on CANCEL and # when the binding was unsuccessful on OK sub set_binding { my ($self, $mod, $sym, $cmds, $cb, $ccb) = @_; $self->clear_command_list; $self->{recording} = 0; $self->{rec_btn}->set_text ("start recording"); $self->{binding} = [$mod, $sym]; $self->{commands} = $cmds; $self->{binding_change} = $cb; $self->{binding_cancel} = $ccb; $self->update_binding_widgets; } # this is a shortcut method that asks for a binding # and then just binds it. sub do_quick_binding { 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 { my ($self) = @_; my ($mod, $sym, $cmds) = $self->get_binding; $self->{keylbl}->set_text (CFClient::Binder::keycombo_to_name ($mod, $sym)); $self->set_command_list ($cmds); } sub get_binding { my ($self) = @_; return ( $self->{binding}->[0], $self->{binding}->[1], [ grep { defined $_ } @{$self->{commands}} ] ); } sub clear_command_list { my ($self) = @_; $self->{cmdbox}->clear (); } sub set_command_list { my ($self, $cmds) = @_; $self->{cmdbox}->clear (); $self->{commands} = $cmds; my $idx = 0; for (@$cmds) { $self->{cmdbox}->add (my $hb = new CFClient::UI::HBox); my $i = $idx; $hb->add (new CFClient::UI::Label text => $_); $hb->add (new CFClient::UI::Button text => "delete", tooltip => "Deletes the action from the record", on_activate => sub { $self->{cmdbox}->remove ($hb); $cmds->[$i] = undef; }); $idx++ } } 1