ファイルを開くダイアログ
バックエンドで、Rustの追加機能であるクレートの1つrfdクレートでファイルを開くダイアログを扱います。まずRustの設定ファイル「Cargo.toml」ファイルでrfdクレートの読み込み設定をします。次に「lib.rs」ファイルのTAURIコマンドload関数でファイルを開くダイアログで開いた.bezierファイルを配列にしてフロントエンドに返します。
ダイアログを扱うrfdクレートの設定
Rustの設定ファイル「src-tauri」→「Cargo.toml」ファイルの[dependencies]で「rfd = "0.15.0"」を追記したら、ビルド時にこのクレートが読み込まれます。
[package]
name = "bezier"
version = "0.1.0"
description = "A Tauri App"
authors = ["you"]
edition = "2021"
[lib]
name = "bezier_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2", features = [] }
[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-shell = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
rfd = "0.15.0" # ファイルダイアログ
.bezierファイルの読み込み
「LoadSavePath」構造体のコンストラクタ「new」メソッドで「data_path」プロパティにリソースディレクトリ(後述の「tauri.conf.json」で設定するディレクトリ)をセットします。ここで初めてファイルを開くダイアログを開くときは、必ずこのディレクトリを開くようにプログラミングします。
次回の保存の処理を実装するまで使いませんが、saved引数に最後に保存したパスが入っていたら、ファイルを開くダイアログでそのディレクトリを最初に開きます。
.bezierファイルのフォーマットは第4回で解説した「_pos」配列の中身そのままで、「コントロールポイントX1,コントロールポイントY1,頂点X1,頂点Y1,コントロールポイントX2,コントロールポイントY2,頂点X2,頂点Y2,・・・」と言う整数の文字列が入っています。
TAURIコマンドload関数で.bezierファイルを読み込んだら「,」区切りで配列に分解し、配列の要素を整数値にパースして配列にして戻り値にします。
// クレート
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,
}
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");
LoadSavePath {
data_path: resource_path.display().to_string(),
}
}
}
// データ読み込みTAURIコマンド関数
#[tauri::command]
fn load(saved: &str,loadsave: State<'_, LoadSavePath>) -> Vec<isize> {
let dir = if saved == "".to_string() { Path::new(&loadsave.data_path) } else { Path::new(&saved) };
let path = FileDialog::new()
.add_filter("Bezier", &["bezier"])
.set_directory(dir)
.pick_file();
let mut data = Vec::new();
if path != None {
let file_path = path.unwrap();
let mut text = "".to_string();
// 文字列読み込み
match fs::read_to_string(file_path) {
Ok(txt) => { text = txt; }
Err(_) => { }
}
// 文字列をデータ配列に
let arr = text.split(',');
for a in arr { data.push(a.parse().unwrap()); }
}
data
}
(後略)
サンプルコードの解説
ファイルを扱う「std::fs」クレートとファイルダイアログを扱う「rfd::FileDialog」クレートを使えるようにします。
「BaseDirectory::Resource」定数で後述するリソースのディレクトリを取得しdata_pathプロパティに代入します。
TAURIコマンドload関数で、FileDialog構造体のインスタンスの「pick_file」メソッドでファイルを開くダイアログを開いて、選択したファイルを「path」変数に代入します。
「read_to_string」関数でファイルから文字列を読み込み「text」変数に代入します。
split関数で「,」区切りに分けて配列にして、「parse」関数で整数値に変換して「data」配列の後ろに追加(push)します。
data配列をTAURIコマンドload関数の戻り値として返します。
TAURIの設定ファイル「tauri.conf.json」
TAURIではインストーラーを自動で生成することは第1回で解説しましたが、その際リソースファイルを同梱することもできます。今回は"resources"に"./data"を追記して、「src-tauri」→「data」フォルダを用意したら一緒に中身も含めてコピーされてインストーラに同梱されます。
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "bezier",
"version": "0.1.1",
"identifier": "com.roxiga.bezier",
"build": {
"frontendDist": "../src"
},
"app": {
"withGlobalTauri": true,
"windows": [
{
"title": "bezier",
"width": 800,
"height": 600
}
],
"security": {
"csp": null
}
},
"bundle": {
"active": true,
"targets": "all",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"resources": [
"./data"
]
}
}
サンプルの.bezierデータ
まだ開けることができる.bezierファイルがないので、簡単なサンプルデータをテキストエディタで作ってみましょう。
今回だけ必ず「src-tauri」→「data」フォルダを作成してその中に次の「sample.bezier」ファイルを、必ず改行文字を入れずに(特に行の末尾にも改行文字を入れない)作成します。ビルド&実行したら、「ファイル」→「開く」メニューでsample.bezierファイルを開いてみてください。次の図のような「12」の絵が表示されます。
327,461,327,461,328,399,328,399,271,399,271,399,262,56,262,56,186,58,186,58,173,116,137,118,137,176,137,176,182,176,182,176,180,399,180,399,124,396,124,396,118,462,118,462,326,462,326,462,625,465,625,465,620,401,621,401,435,403,435,403,601,266,602,170,588,50,484,56,384,66,388,129,444,142,444,142,526,89,522,177,497,312,326,411
おわりに
今回はプログラミング言語Rustでファイルを開くメニューの実装や、rfdクレートを追加してファイルダイアログの実装、ベジェ曲線データを読み込む実装をしました。
次回は、連載の最終回になります。保存メニューを追加してベジェ曲線データをファイルに保存できるようにしてお絵描きアプリが完成します!
