開発

[binllion] レイアウトを複雑に組む

前回の処理でスクロールできるようになりましたがヘッダーもスクロールしてしまいました。

ヘッダーは固定してデータ部分のみスクロールするようにしたいです。

現状は同じParagraphの中にヘッダーとデータの情報が入ってしまっているのでこれを分離すれば意図した通りになると思います。

そこで、レイアウトを細かく設定してヘッダーとデータの領域も分けました。

レイアウトの処理をrender_main()で行っていましたが、render_prep()にコードを移動して、更に細かくレイアウトをします。

レイアウトはネストして設定できるので、これを使ってヘッダーとデータの領域を分けます。

算出したレイアウトはmessageに新しく配列を追加してrender_main()で利用できるようにします。

pub(crate) fn render_prep(terminal: &mut DefaultTerminal, message: &mut Message) -> io::Result<()> {
    let frame = terminal.get_frame();

    // 左右に50%分割
    let main_layout = Layout::default()
        .direction(Direction::Horizontal)
        .constraints(vec![Constraint::Percentage(50), Constraint::Percentage(50)])
        .split(frame.area());

    // 右側を上下に50%分割
    let sub_layout = Layout::default()
        .direction(Direction::Vertical)
        .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
        .split(main_layout[1]);

    // 左側をヘッダーとコンテンツに分割
    let inner_main = Layout::default()
        .direction(Direction::Vertical)
        .constraints([Constraint::Length(1), Constraint::Min(1)])
        .margin(1)
        .split(main_layout[0]);

    // 右上側をヘッダーとコンテンツに分割
    let inner_sub0 = Layout::default()
        .direction(Direction::Vertical)
        .constraints([Constraint::Length(1), Constraint::Min(1)])
        .margin(1)
        .split(sub_layout[0]);
.....
    // レイアウトの保存
    let screen_layout = message.layout_mut();
    screen_layout[0] = main_layout;
    screen_layout[1] = sub_layout;
    screen_layout[2] = inner_main;
    screen_layout[3] = inner_sub0;
.....
Code language: Rust (rust)
pub(crate) struct Message {
    bin_data: BinData,
    cursor: CursorPosition,
    scroll: Scroll,
    layout: [Rc<[Rect]>; 4], // main_layout, sub_layout, inner_main, inner_sub
}
Code language: Rust (rust)

render_main()では下記のようにヘッダーとデータを分離してレンダリングするようにしています。

これでスクロールが意図通り行われるようになりました。

    // メインパネル

    // 16進数ヘッダー
    let hex_header = Line::from(format!(
        "{:width$} +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F",
        " ",
        width = 8
    ));

    let mut main_panel_data = Vec::new();
    // main_panel_data.push(hex_header);
    main_panel_data.append(&mut Converter::convert_to_lines::<ForHex>(
        bin_data.buf(),
        constants::LINE_LEN,
    ));

    let main_contents =
        Paragraph::new(Text::from(main_panel_data)).scroll((message.scroll().scroll_y()[0], 0));
    // .block(block.clone());
.....
    let _ = terminal.draw(|frame| {
        let main_panel = layout[0][0];
        let main_header = layout[2][0];
        let main_area = layout[2][1];
.....
        frame.render_widget(&block, main_panel);
        frame.render_widget(hex_header, main_header);
        frame.render_widget(main_contents, main_area);
.....
Code language: Rust (rust)

GitHubにコードをアップロードしています。0.1.0バージョン

コードのコメントに書かれているfirst_stepなどをcargoコマンドに渡すと実行できます。

# Example
$ cargo run --example first_stepCode language: Bash (bash)
管理人

Recent Posts

情報セキュリティマネジメント試験取得への道

スキルアップを図るべく情報セキ…

2か月 ago

ファイナンシャルプランナー3級試験取得への道

スキルアップを図るべくファイナ…

2か月 ago

[rust] New Type Patternを使ってみる

DDDの考えを取り入れることで…

5か月 ago

RustでDDDの要素を取り入れてみる

前回SOLID原則というものを…

5か月 ago

期間限定!書籍無料キャンペーン2025

「mdBookではじめるKin…

5か月 ago