捕获了Curses :: UI :: Grid选项卡

时间:2014-06-06 03:05:56

标签: perl curses

我使用Curses :: UI :: Grid来显示表格数据。该窗口由一个表和几个按钮组成,用于将数据显示窗口导航到其他窗口,如下所示: Curses::UI::Grid tabular data sample

然而,当显示数据时,焦点转到第一行,如果我使用选项卡将焦点转移到下一个UI控件,它永远不会转到底部的按钮。它只是循环通过第一行的单元格。

以下是重现问题的代码:

#!/usr/bin/env perl

use strict;
use warnings;
use Curses::UI;
use Curses::UI::Grid;

my $debug = 0;

# Create the root object.
my $cui = new Curses::UI ( 
    -color_support => 1,
    -clear_on_exit => 1, 
    -debug => $debug,
);

create_promote_deps_window();
$cui->set_binding( \&exit_dialog , "\cQ");

$cui->mainloop();

sub exit_dialog {
    my $return = $cui->dialog(
        -message   => "Do you really want to quit?",
        -title     => "Confirm",
        -buttons   => ['yes', 'no'],
    );

    exit(0) if $return;
}

sub create_base_window {
    my ($name) = @_;

    $cui->add(
        $name,
        'Window', 
        -border       => 1, 
        -titlereverse => 0, 
        -padtop       => 2, 
        -padbottom    => 3, 
        -ipad         => 1,
        -title        => 'CTRL-Q to quiz',
    );
}

sub create_promote_deps_window {
    my ($name) = @_;

    my $win = create_base_window($name);

    my $grid = $win->add(
        'grid',
        'Grid',
        -height       => 14,
        -width        => -1,
        -editable     => 0,
        -border       => 1,
        -process_bindings => {
            CUI_TAB => undef,
        },
        # -bg       => "blue",
        # -fg       => "white",
    );

    $grid->add_cell(
        "otp",
        -width => 10,
        -label => "OTP"
    );

    $grid->add_cell(
        "commit1",
        -width => 10,
        -label => "Commit#"
    );

    $grid->add_cell(
        "otnp",
        -width => 10,
        -label => "OTNP"
    );

    $grid->add_cell(
        "commit2",
        -width => 10,
        -label => "Commit#"
    );

    $grid->add_cell(
        "overlap",
        -width => 32,
        -label => "Overlap"
    );

    my $button_callback = sub {
        my $this = shift;

        my $btn_name = $this->get();
        if ($btn_name eq "Back") {
            # give up promotion and return to promote window
            $win->focus();
        }
        elsif ($btn_name eq "PromoteWithDeps") {
        }
    };
    $win->add(
        undef,
        'Buttonbox',
        -y        => -1,
        -buttons  => [
            {
                -label   => "< Back >",
                -value   => "Back",
                -onpress => $button_callback,
            },
            {
                -label   => "< Promote w/ all deps >",
                -value   => "PromoteWithDeps",
                -onpress => $button_callback,
            },
        ],
    );

    my @data = (
        ['HDT-10', 'e3042b0', 'HDT-7', '6741e47', 'src/tc/b.p'],
        ['HDT-10', 'e3042b0', 'HDT-7', '6741e47', 'src/tc/a.p'],
        ['HDT-10', 'e3042b0', 'HDT-7', '6741e47', 'src/tc/c.p'],
        ['HDT-10', 'e3042b0', 'HDT-7', '66a3254', 'src/tc/c.p'],
        ['HDT-10', 'e3042b0', 'HDT-7', '66a3254', 'src/tc/b.p'],
        ['HDT-10', 'e3042b0', 'HDT-7', '66a3254', 'src/tc/a.p'],
        ['HDT-10', 'e3042b0', 'HDT-8', '8b65677', 'src/tc/e.p'],
        ['HDT-10', 'e3042b0', 'HDT-8', '8b65677', 'src/tc/d.p'],
        ['HDT-10', 'e3042b0', 'HDT-9', '3eefa90', 'src/tc/f.p'],
    );
    foreach my $f (@data) {

        $grid->add_row(
            undef,
            # -fg    => 'black',
            # -bg    => 'yellow',
            -cells => {
                otp     => $f->[0],
                commit1 => $f->[1],
                otnp    => $f->[2],
                commit2 => $f->[3],
                overlap => $f->[4],
            }
        );
    }

    $grid->layout();
    return $win;
}

如何自定义Tab键顺序,以便用户可以将焦点移动到Curses :: UI :: Grid下面的按钮?

谢谢!

1 个答案:

答案 0 :(得分:1)

你遇到网格标签的困难不在于窗口的标签排序,而在于Curses :: UI :: Grid为Tab和Shift +提供了自己的绑定标签。一个基本的解决方案是在网格具有焦点时按下Tab和Shift + Tab时提供自己的处理程序:

sub move_focus {
    my $widget = $_[0];
    my $key    = $_[1];

    if ($key eq "\t") {
        $widget->parent()->focus_next();
    }
    else {
        $widget->parent()->focus_prev();
    }
}

然后,您可以将此处理程序绑定到网格:

$grid->set_binding(\&move_focus, "\t");
$grid->set_binding(\&move_focus, KEY_BTAB());

但是,您可能会发现使用光标键在单元格之间移动是单调乏味的,因此您可能仍希望能够在单元格之间进行制表,并且只有当光标位于行尾时才跳转到按钮。在这种情况下,您的自定义处理程序需要更加智能化:

sub move_focus {
    my $grid = $_[0];
    my $key  = $_[1];

    if ($key eq "\t") {
        my $last_cell = $grid->get_cell($grid->{_cells}[$#{$grid->{_cells}}]);
        if ($grid->get_foused_cell() == $last_cell) {
            $grid->parent()->focus_next();
        }
        else {
            $grid->next_cell();
        }
    }
    else {
        my $first_cell = $grid->get_cell($grid->{_cells}[0]);
        if ($grid->get_foused_cell() == $first_cell) {
            $grid->parent()->focus_prev();
        }
        else {
            $grid->prev_cell();
        }
    }
}