世界を動かす技術を、日本語で。

RustのクロスプラットフォームGPUIコンポーネント

概要

GPUI Componentは、Rust製のデスクトップアプリ向けUIコンポーネント集。 macOS・Windows風のモダンなデザインと高いカスタマイズ性を両立。 Markdownやコードエディタ、チャートなど多機能を搭載。 高パフォーマンスなバーチャライズドテーブル・リストに対応。 開発中であり、導入はGit依存・ドキュメントも簡易的なもの。

GPUI Componentの特徴

  • 60種類以上 のクロスプラットフォーム対応UIコンポーネント
  • macOS/Windows風の操作感shadcn/ui デザインの融合
  • Stateless RenderOnce 形式で、シンプルかつ直感的な利用性
  • Theme/ThemeColor による多彩なテーマ・変数ベース設定
  • xs/sm/md/lg の柔軟なサイズ指定
  • Dockレイアウト によるパネル配置、リサイズ、自由なTilesレイアウト
  • バーチャライズドテーブル・リスト で大規模データも滑らか表示
  • Markdownと簡易HTML のネイティブ描画
  • 内蔵チャート でデータ可視化
  • LSP対応・20万行対応のコードエディタ 搭載
  • Tree Sitter によるエディタ・Markdownのシンタックスハイライト

Showcaseとマルチテーマ

  • Longbridge Pro がGPUI Componentで構築された初のアプリケーション事例
  • アプリ側で 独自のマルチテーマ 実装が可能(GPUI Component標準機能ではないが、Theme機能ベースで容易に実装可能)

導入方法

  • 開発中のため、依存追加はGit指定

    • gpui = "0.2.2"
    • gpui-component = "0.3.0"
  • 基本的な利用例(HelloWorld表示+ボタン配置)

    • Window/Context/Root の組み合わせで構築
    • gpui_component::init(cx)呼び出しが必須
    use gpui::*;
    use gpui_component::{button::*, *};
    pub struct HelloWorld;
    impl Render for HelloWorld {
        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
            div().v_flex().gap_2().size_full().items_center().justify_center()
                .child("Hello, World!")
                .child(
                    Button::new("ok")
                        .primary()
                        .label("Let's Go!")
                        .on_click(|_, _, _| println!("Clicked!")),
                )
        }
    }
    fn main() {
        let app = Application::new();
        app.run(move |cx| {
            gpui_component::init(cx);
            cx.spawn(async move |cx| {
                cx.open_window(WindowOptions::default(), |window, cx| {
                    let view = cx.new(|_| HelloWorld);
                    cx.new(|cx| Root::new(view.into(), window, cx))
                })?;
                Ok::<_, anyhow::Error>(())
            }).detach();
        });
    }
    

WebView機能

  • WryベースのWebView要素 をオプションで利用可能
    • まだ初期実装段階、制限多数
    • gpui-component = { version = "0.3.0", features = ["webview"] }
    • wry = { version = "0.53.3", package = "lb-wry" }

アイコン利用

  • Icon要素 はSVGファイルを標準搭載していない
    • 例ではLucideアイコンを使用
    • 独自SVGをIconNameに従い命名しプロジェクトに追加可能

開発とサンプル

  • アプリギャラリー・examplesディレクトリ で多数サンプル公開
  • cargo runcargo run --example <example_name>で実行可能
  • 詳細は CONTRIBUTING.md 参照

他ライブラリとの比較

| 機能 | GPUI Component | Iced | egui | QT 6 | |---------------------|---------------|-----------|--------------|-----------| | 言語 | Rust | Rust | Rust | C++/QML | | レンダラー | GPUI | wgpu | wgpu | QT | | ライセンス | Apache 2.0 | MIT | MIT/Apache2.0| 商用 | | 最小バイナリサイズ | 12MB | 11MB | 5MB | 20MB | | クロスプラットフォーム | Yes | Yes | Yes | Yes | | ドキュメント | No | Simple | Simple | Good | | Web対応 | No | Yes | Yes | Yes | | UIスタイル | Modern | Basic | Basic | Basic | | CJKサポート | Yes | Yes | Bad | Yes | | チャート | Yes | No | No | Yes | | テーブル(大規模) | Yes | No | Yes | Yes | | テーブル列リサイズ | Yes | No | Yes | Yes | | テキスト基盤 | Rope COSMIC | Text 3 trait | TextBuffer | QTextDocument | | コードエディタ | Simple | Simple | Simple | Basic API | | Dockレイアウト | Yes | Yes | Yes | Yes | | シンタックスハイライト | Tree Sitter | Syntect | Syntect | QSyntaxHighlighter | | Markdown描画 | Yes | Yes | Basic | No | | Markdown+HTML混在 | Yes | No | No | No | | HTML描画 | Basic | No | No | Basic | | テキスト選択 | TextView | No | Any Label | No | | テーマ | Yes | No | No | No | | I18n | Yes | Yes | Yes | Yes |

ライセンスとクレジット

  • Apache-2.0ライセンス
  • UIデザインは shadcn/ui、アイコンは Lucide より

注意事項・フィードバック

  • 誤りや古い情報 があればIssueまたはPRで報告推奨
  • 詳細なリリース情報・バイナリサイズ削減方法などは脚注参照

Hackerたちの意見

これは、利用可能なウィジェットやコンポーネントの観点から見ても、最も完成度の高いRustのUIクレートの一つみたいだけど、残念ながらまだほとんど使われてないね。ドキュメントは進んできてるみたいだけど。もう一つ、すごく完成度が高いのは、fyroxゲームエンジンで使われているfyrox-uiだよ。https://crates.io/crates/fyrox-ui でも、これもfyroxの外ではあまり知られてない。RustのUIシーンは成熟してきてるけど、人気のある選択肢(iced、egui、dioxus、slintなど)は、今のところコンポーネントの完成度では一番ではない気がする。アップデート:これ、正直すごくて、RustのUIの風景に大きな進展をもたらしてる。ここで、彼らのコンポーネントを全部見せる素晴らしいウィジェットギャラリーアプリが動かせるよ: https://github.com/longbridge/gpui-component/tree/main/crate... ただ「cargo run --release」ってやるだけ。

RustのUIシーンは成熟してきてるけど、人気のある選択肢(iced、egui、dioxus、slintなど)は、今のところコンポーネントの完成度では一番ではない気がする。問題の一部は、まだまだ変化が激しいからだと思う。でも、ここには本当に勢いがあるし、私の経験では、今日はRustで非常にリッチでエンタープライズ向けのUIを構築できたよ。

更新: これ、正直すごく見えるし、RustのUIの世界で大きな進展を遂げてるね。ここで彼らのコンポーネントを全部見せるすごいウィジェットギャラリーアプリが動かせるよ: > https://github.com/longbridge/gpui-component/tree/main/crate... > 「cargo run --release」だけで動く。すごいね!ただ、900個くらいの依存関係を使ってるのが気になるけど、GUIアプリにはそれが多いのかはわからないな。

UIシーンが成熟していると思っているなら、1. デザインドキュメントと2. デバッグインフラドキュメント(検証、テスト、ステッピング、ロギング、トレース、録画、スケジューリング、逆計算などの一般的なもの)をどこで見つけられるか、またはそれらをどう適用するか教えて?

Rustを使ってる人には素晴らしいね。ただ、スクリーンリーダーや他のアクセシブルな技術でどれだけうまく動くのか、ちょっと気になるな。

新しいUIフレームワークを見るたびに、毎回思う一番の質問。

自分でコードを実行してみたことはないけど、彼らのAPIドキュメントにはアクセシビリティについて触れてるね: https://longbridge.github.io/gpui-component/docs/components/... ドキュメントが正しければ、必要な説明やラベルを実装すればUIコントロールはARIAに準拠してるみたい。

基盤となるオープンソースソフトウェアが、取引や暗号通貨、マネーロンダリングの会社によって作られたり維持されたりしているのは悲しいことだと思う。でも、逆に彼らが少なくとも社会に何かを貢献しているのは素晴らしいことだね!

ビットコインの精神(つまり、元々の「銀行は壊れてる、これを直そう」)は、ハッカーの精神(「このもの/プログラムは壊れてる、これを直そう」)に似てるから、あまり驚くことではないかもね?短期的な痛みは長期的な利益のために、みたいな感じで。(免責事項:私はビットコインはバカだと思ってるけど、市場はそう思ってないみたい。)

それがたくさんあるとは思えないな。

gpui自体は、https://zed.dev の人たちによってメンテナンスされているよ。それに、LongbridgeはこのGPUIコンポーネントライブラリを使っているみたいで、Longbridge Pro [1] アプリも、普通のオンライン証券会社に見えるんだけど、それに対して何か問題があるの? 1: https://longbridge.com/desktop/

RustにはもっとGUIコンポーネントのコレクションが必要だね。GUIツールキットはたくさんあるけど、どれでも使えるプリビルドのコンポーネントは比較的少ない。これのコレクションはかなり便利そうだけど、コンポーネントリストはウェブフレームワークのコンポーネントリストとほとんど区別がつかない。webviewコンポーネントだけが、ネイティブアプリケーションに特有のように見える。だから、ファイルオープンダイアログみたいなものには、rfd [1] を使わなきゃいけなくて、スタイリングの一貫性が失われるね。https://docs.rs/rfd/latest/rfd/

自分のファイルピッカーを作るんじゃなくて、常にネイティブのファイルピッカーを使うべきだよ。それがいいことだね。

今はほとんどのUIライブラリが自分のウィジェットを描画してるけど、ネイティブな統合はほぼいつも使われたり求められたりしてるよ。そういう統合には、キーボードショートカット、ネイティブシステムメニュー(macOS)、ネイティブファイルダイアログ、そして(時々)ネイティブコンテキストメニューが含まれる。忘れてるものもあるかもしれないけど、こういう最小限の統合はユーザーにとって親しみやすさを感じさせるからいいことだね。

スタイリングの一貫性が失われる そうだね。それは(ほぼ常に¹)良いことだよ。アプリのデザイナーやプロダクトオーナーは、自分たちのアプリが「プラットフォーム間で一貫して見える」ことを望むけど、ユーザーはファイルダイアログやウィンドウの枠、メニューなどが一貫していることを求めているんだ。でも、彼らにとっての一貫性は、日常的に使う20以上の他のアプリと一貫していることを意味するんだよ。だから、ネイティブが重要なんだ。¹ 明らかに一部のソフトウェアは例外だけど。例えば、BlenderやAutoCAD、Photoshop/CSのような「専門ソフトウェア」では、ダイアログがa) ニッチなワークフローに最適化されていて、b) ユーザーがOSをアップグレードしたり、OS間を移動したりする時に一貫性を保つ必要があるんだ。でも、それは例外だよ。TODOリストアプリやPDFリーダーは、ほぼ間違いなくそうじゃない。

これは「ウェブじゃない」ネイティブなのか、それとも実際にネイティブのテキスト入力やスクロールウィジェットを使ってるネイティブなのか?Javaの世界が発見したように、かなり大きな違いがあるよ。

「ネイティブ」ってのは「ウェブじゃない」って意味だと思う。私の知る限り、いろんなGPU APIを使って描画されてるよ(例えば、GPUIはmacOSではMetalから始まった)。

「ネイティブ」ってのは「ネイティブ実行ファイル」って意味だと思う。GPUIは「ネイティブOSウィジェット」じゃないし。

「ネイティブ」ってのは「ウェブじゃない」ってこと。OS統合なし。

macOSはネイティブアプリを作れる唯一のOSだよ。LinuxにはGTKとQTという、いくつかのディストリビューションでネイティブと見なされるGUIフレームワークがあるけど、WindowsにはMSがシェルのために使っているフレームワークやアプローチがたくさんあって、Webviewさえもネイティブと見なされることがあるんだ。

仮想化されたリストやテーブルは素晴らしいよ!多くのUIフレームワークにはこれがなくて、自分で作らなきゃいけないんだ...

これってアクセシビリティを実装してるの?これはRustのUIフレームワークにしばしばある問題で、見た目は美しいけど、アクセシビリティが必要になると、アプリ全体を廃棄して、もっと成熟したものに書き直さなきゃいけなくなるんだよね。

うん

最もシンプルな例でも、依存関係が千以上あるよ(文字通り)。その中にはGTK、GDK、pangoなどが含まれてる。別のツールキットに依存しているって、個人的には一番変なことだと思う。

これ、Linuxでは結構一般的だと思うよ。トップレベルのウィンドウやシステムメニューとかを描画するには、GTKかQtを使うのがいいんじゃないかな。UI自体はGPUキャンバスで描画されるけどね。

こういうのを動かしてる時のバッテリーライフが気になるな。もう一つ興味があるのは、テクスチャへのレンダリングをサポートしてるかどうか。ゲームの中でオブジェクト(例えばモニター)にテクスチャとして使ったり、画面上に四角形や三角形で不透明度を持たせてUIレイヤーやHUDとしてレンダリングしたりするのに使えるのかな。