おっさんになると、体が劣化してくる。
白髪や皮膚のたるみ、シミなど、外見上のものは仕方がないと諦めるしか無い。
基本的に外見は生きる上で実害はあんまりない。(この考え方が既におっさんか…)
ロマンスグレーで素敵とか、プラスにも働く。いや、素敵ではないな。単なるお世辞か。
デスクワーカーの恐怖の問題は「老眼」。
なんだか字がよく見えなくなる。以前は平気だった 8pt のフォントが妙に小さい。
そんなとき、ふと職場の年かさの人が、暗い色使いでコーディングをしていたことを思い出した。
鴨の羽色の背景色(#008080 : つまり Windows 95 のデスクトップの色)にグレーの文字。見辛い。
ところが最近、背景が白で黒い小さな文字だと明るすぎて見えなくなってくることに気づいた。
なんだかすぐ目が疲れる。
そこで、emacs の color-theme を clolor-theme-dark-blue2 にした。
濃紺の背景に、グレーの文字で読みやすい。SFCのファイナル・ファンタジーの色っぽくて郷愁にかられる。
せっかくだからテストで使う画像も比較的暗い色を選ぼう。
とはいえ、あんまり暗いと繊細なおっさんの心に影を落とすから、やっぱり明るいのを選ぼう。
先日行った愛宕山の写真*1にしてみた。
だけど画像を表示させようとすると、やっぱりコンパイルエラーが出る。
というわけで iced の仕組みや動きをちゃんと調べてみた。
Application トレイト, Sandbox トレイト
ドキュメント によると Application トレイトは、メソッドが Command を返すことで、Command が非同期に(アプリケーションの描画とは別に)実行される。
非同期に実行される必要がなければ、Command の実行がない Sandbox トレイトを使う方がシンプルで良い。
画面ステータスの構造体にこのトレイトを実装することで run メソッドも追加され、GUI が表示される。
Application::view メソッド
画面の表示が定義されたウィジェットを返す。
返り値の型である Element は汎用的なウィジェットの型。
Column と Row は、widget モジュールで定義された型。インスタンスに対してウィジェットを push して並べる。
Column.new().push(ウィジェット).push(ウィジェット)
widget
ウィジェット(ボタン、スライダー、画像、キャンバスなど)は widget モジュール で定義されている。
Image ウィジェット
Image ウィジェットは、Cargo.toml に iced に対して features=["image"] を指示する必要がある。
iced = { version = "0.1.1", features=["image"] }
そうしないと iced_wgpu の Image が参照されてしまい、型違いで Column 型のインスタンスに push できない(コンパイルエラー)。
width や height メソッドで、縦横の比率を保ったまま縮小してくれる。
ただし、これらメソッドで指定できるのは元の画像のサイズまで。
それ以上大きい値を指定しても拡大はしてくれない。
理由
ソースコード をから推察してみる。
Image 型に対する Widget トレイトの実装で、layout メソッドが定義されている。
この layout メソッドの最初で renderer.dimensions(&self.handle) の返り値にて、元画像の幅と高さを width と height にセットしている。
このあと、size の定義で、layout::Limit 型の resolve メソッドで大きさを丸めてしまっているように思える。
で、ようやっと動くようになった。前述の通り、画像のサイズはオリジナル以上には拡大できないみたい。
Canvas ウィジェットで RGB を表示するようにして、拡大を自分で実装してみようかと考えている。
use iced::{ button, executor, Application, Button, Column, Command, Element, Image, Length, Settings, Text, }; fn main() { Viewer::run(Settings { ..Settings::default() }) } // State - the state of my application struct Viewer { width: u16, button: button::State, } // Message - event that we care about #[derive(Debug, Clone, Copy)] // derive Debug, Clone, Copy trait pub enum Message { ExpandPressed, } impl Application for Viewer { // Use default type Executor = executor::Default; type Message = Message; type Flags = (); fn new(_flags: ()) -> (Self, Command<Message>) { ( Viewer { width: 100, button: button::State::new(), }, Command::none(), ) } fn title(&self) -> String { "atagosan".to_string() } // Update logic: connect events to functions fn update(&mut self, message: Message) -> Command<Message> { match message { Message::ExpandPressed => { self.width += 10; } } Command::none() } // View Logic fn view(&mut self) -> Element<Message> { // Use a column: a simple vertical layout Column::new() .push( Button::new(&mut self.button, Text::new("expand the image")) .on_press(Message::ExpandPressed), ) .push( Image::new("/home/chrono/rust/kilo/atagosan.jpg").width(Length::Units(self.width)), ) .push( // The message Text::new(format!("愛宕山({})", self.width)), ) .into() } }
*1: