ファイルにベジェ曲線データを保存する
最後にフロントエンドから送られたベジェ曲線データをファイルに保存する機能を実装します。「ファイルに名前を付けて保存」するダイアログは、デフォルトではデスクトップフォルダが開かれます。

ベジェ曲線データを名前を付けて保存する
以下のサンプルコード[3]を追記して、プロジェクトをデバッグビルドして実行したら、何らかの絵を描いて「ファイル」→「名前を付けて保存」メニューを実行してください。すると、次の図のようにファイルダイアログが表示されます。ファイル名を付けて保存すると、引数のベジェ曲線データを「,(コンマ)」区切りで1行の文字列に変換して、テキスト形式でファイルに保存します。
戻り値の「_saved」変数に最後に保存したファイルのパスが入っており、ファイルを開くダイアログを開くときにそのディレクトリを最初に開きます。

// クレート use tauri::{menu::*, AppHandle, Wry, Error, State, Manager, App, path::BaseDirectory}; use std::fs; use rfd::FileDialog; use std::path::Path; // 読み込み書き込みパス構造体 struct LoadSavePath { data_path: String, desktop_path: String, } impl LoadSavePath { fn new(app:&mut App) -> Self { let path = Path::new("data"); let bd = BaseDirectory::Resource; let resource_path = app.path() .resolve(path,bd) .expect("failed to resolve resource"); let desktop_path = app.path() .desktop_dir() .expect("failed to resolve resource"); LoadSavePath { data_path: resource_path.display().to_string(), desktop_path: desktop_path.display().to_string(), } } } (中略) // データ保存TAURIコマンド関数 #[tauri::command] fn save(data: Vec<isize>,loadsave: State<'_, LoadSavePath>) -> String { let dir = Path::new(&loadsave.desktop_path); let path = FileDialog::new() .add_filter("Bezier", &["bezier"]) .set_directory(dir) .save_file(); if path != None { let file_path = path.unwrap(); let mut arr = Vec::new(); // データ配列を文字列に for d in data { arr.push(d.to_string()); } let text = arr.join(","); // 文字列の保存 fs::write(file_path.clone(), text).unwrap(); file_path.display().to_string() } else { "".to_string() } } (後略)
サンプルコードの解説
LoadSavePath構造体のコンストラクタ「new」メソッドで、デスクトップのパスを「desktop_path」プロパティに代入します。
TAURIコマンドsave関数でデスクトップのパスを取得して、「名前を付けて保存」ダイアログを開いてファイルを保存する場合、引数の「data」配列の各要素を文字列に変換して「arr」配列に追加します。arr配列を「,」区切りで1行の文字列に繋ぎ(joinメソッド)、「text」変数に代入します。「write」関数でtext変数をファイルに保存します。そのファイル名を戻り値として返します。
ファイルを保存しない場合は空のファイル名を戻り値として返します。
コラム「ステート機能」
なぜデスクトップのパスやリソースのパスをわざわざ構造体で持つのか不思議に思った人も少なくないでしょう。それは「App」構造体でアプリの情報をTAURIコマンド関数の中に受け渡すために必要だからです。App構造体のインスタンスが得られなければ、作ったアプリのリソースフォルダのパスが得られないのです。
「State」のステート機能を使えば、run関数とTAURIコマンド関数の間でデータを受け渡すことができるようになります。例えばプログラミング言語「C/C++」なら「グローバル変数」を使ってできますが、Rustはグローバル変数が使えないため、ステート機能を使います。
おわりに
今回はプログラミング言語「Rust」で、バックエンドでメニューを追加したり、フロントエンドからバックエンドにお絵描きデータを渡したり、お絵描きデータを保存したりしました。
これで連載は終了です。Tauri 2.0もRustもまだまだ書き足りないことばかりですが、ここで一旦終わりにしたいと思います。