前回の処理でスクロールできるようになりましたがヘッダーもスクロールしてしまいました。
ヘッダーは固定してデータ部分のみスクロールするようにしたいです。
現状は同じ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;
.....
pub(crate) struct Message {
bin_data: BinData,
cursor: CursorPosition,
scroll: Scroll,
layout: [Rc<[Rect]>; 4], // main_layout, sub_layout, inner_main, inner_sub
}
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);
.....
TOC
- 準備
- ターミナル入出力を試す
- ターミナル系crateを利用する
- 編集データと表示処理
- 画面制御
- その他
GitHubにコードをアップロードしています。
コードのコメントに書かれているfirst_stepなどをcargoコマンドに渡すと実行できます。
# Example
$ cargo run --examples first_step