- Spot adalah toolkit reaktif sederhana untuk membuat GUI desktop lintas platform di Go; ia menggunakan widget native jika memungkinkan dan menyediakan API yang konsisten untuk tiap platform
- Saat status aplikasi berubah, Spot membangun ulang pohon komponen immutable lalu membandingkannya dengan status sebelumnya untuk menentukan kontrol UI mana yang perlu diperbarui
- Backend saat ini berbasis Cocoa untuk macOS dan FLTK untuk platform lain; di macOS, FLTK juga bisa digunakan secara opsional
spotadalah paket inti yang tidak bergantung pada backend, menyediakan model reaktif dan rendering, sedangkanspot/uiadalah kumpulan kontrol GUI lintas platform siap pakai- Tata letak otomatis, banyak jendela, dialog modal, jendela yang dapat diubah ukurannya, menu bar, widget kustom, akses ke widget native, drag-and-drop, dan internasionalisasi belum tersedia
Tujuan dan model dasar Spot
- Spot adalah toolkit GUI reaktif untuk Go, dirancang untuk menggunakan widget native jika memungkinkan sekaligus menyediakan API yang konsisten di berbagai platform
- Dengan menambahkannya sebagai dependensi sederhana ke proyek dan hanya menulis kode Go, Anda dapat membuat binary GUI native yang self-contained tanpa alat tambahan atau code generation
- Contohnya membuat jendela dan tombol dengan alur
ui.Init(),spot.MountFn(...),ui.Run(), serta mengelola status jumlah klik denganspot.UseState[int](<https://github.com/roblillack/ctx, 0>) - Handler klik tombol memanggil
setCounter(counter + 1), dan ketika status berubah, judul tombol berubah dalam format"Clicked %d times!"
Cara pembaruan reaktif
- Di Spot, reactive berarti UI diperbarui secara otomatis saat status aplikasi berubah
- Saat status berubah, Spot membangun ulang pohon komponen immutable, lalu membandingkannya dengan cepat terhadap status sebelumnya untuk menentukan kontrol UI mana yang akan diperbarui
- Di web, gagasan ini sering disebut virtual DOM, dan Spot bermula dari eksperimen membawa konsep ini ke lingkungan desktop Go untuk mengimplementasikan library GUI yang mirip React
- Alih-alih memperbarui UI secara manual, developer mengelola logika dan status aplikasi dengan fungsi rendering tanpa efek samping serta hook seperti
UseState
Backend dan struktur paket
- Spot secara otomatis memilih backend yang sesuai dengan platform eksekusi saat kompilasi
- Saat ini tersedia dua backend
- Implementasi berbasis FLTK: menggunakan go-fltk
- Implementasi berbasis Cocoa: menggunakan versi modifikasi dari gocoa
- Di macOS, Spot menggunakan backend Cocoa, sedangkan di platform lain menggunakan backend berbasis FLTK
- Di macOS, FLTK juga bisa digunakan secara opsional, dan peningkatan dukungan Windows masih menjadi rencana ke depan
spotadalah paket inti yang menyediakan model reaktif dan kemampuan rendering, serta dapat digunakan dengan kumpulan kontrol apa pun yang mengimplementasikan antarmukaspot.Controlspot/uiadalah paket kontrol GUI lintas platform siap pakai yang dapat digunakan bersama Spot
Komponen, kontrol, dan hook
- Seperti React, Anda dapat membuat hook kustom
- Buat fungsi yang menerima
*spot.RenderContextsebagai argumen pertama, lalu panggilspot.UseState,spot.UseEffect, dan lainnya untuk menghubungkannya ke lifecycle Spot - Secara konvensi, nama fungsi diberi prefiks
Use…
- Buat fungsi yang menerima
- Komponen kustom dapat dibuat sebagai struct yang mengimplementasikan antarmuka
spot.Component- Antarmuka ini memiliki satu metode,
Render(ctx *spot.RenderContext) spot.Component - Komponen yang dibuat dengan cara ini dapat digunakan dengan cara yang sama seperti komponen bawaan
- Antarmuka ini memiliki satu metode,
- Di Spot, component adalah unit logis yang memuat logika bisnis dan status
- Komponen tersusun dari komponen lain, dan pada akhirnya dirender menjadi satu atau lebih kontrol
- control adalah komponen khusus yang di-mount ke pohon UI dan merepresentasikan elemen visual di layar
- Umumnya berbasis implementasi native dari backend GUI, seperti tombol, label, atau input teks
- Library widget yang sepenuhnya berbeda dari library widget yang disediakan juga dapat digunakan
- Cukup buat struct yang mengimplementasikan antarmuka
spot.Componentdan mengelola widget native
- Cukup buat struct yang mengimplementasikan antarmuka
- Penggunaan
spot/uidengan backend selain Cocoa atau FLTK saat ini belum didukung
Istilah lifecycle rendering
- Make: proses membuat instance struct yang mengimplementasikan antarmuka
spot.Component, atau memanggilspot.Makebersama fungsi render untuk membuat instance komponen baru - Render: proses menerapkan status komponen ke elemen penyusunnya dan mengembalikan instance komponen lain
- Build: proses merender komponen secara rekursif untuk membuat pohon kontrol
- Dilakukan dengan meneruskan instance komponen ke
spot.Build, atau meneruskan fungsi render kespot.BuildFn
- Dilakukan dengan meneruskan instance komponen ke
- Mount: proses membuat kontrol UI nyata dari pohon kontrol virtual
- Dapat dilakukan dengan memanggil
Mountpada node pohon, atau menggunakanspot.Mount,spot.MountFn
- Dapat dilakukan dengan memanggil
- Update: proses memperbarui pohon kontrol yang sudah di-mount
- Dilakukan dengan memanggil
Updatepada node pohon
- Dilakukan dengan memanggil
Fitur yang saat ini belum disediakan
- Spot saat ini belum menyediakan fitur berikut
-
Tata letak otomatis
- Banyak jendela
- Dialog modal
- Jendela yang dapat diubah ukurannya
- Menu bar
- Widget kustom
- Akses ke widget native
- Drag-and-drop
- Internasionalisasi
-
Kontrol UI yang didukung
- Spot menyediakan beberapa kontrol UI secara default, seperti tombol, label, input teks, slider, dan dropdown
- Penanda status dukungan dibagi menjadi ❓ belum diimplementasikan, 🚧 sedang dikerjakan, ⚠️ implementasi parsial, dan ✅ selesai
- Kontrol utama yang sudah selesai adalah sebagai berikut
- Button: tombol untuk menjalankan aksi sederhana, menggunakan
Fl_ButtondanNSButton - Checkbox: kontrol untuk memilih salah satu dari dua opsi, menggunakan
Fl_Check_ButtondanNSButton - Dropdown: dropdown untuk memilih salah satu dari beberapa item, menggunakan
Fl_ChoicedanNSComboBox - Image: kontrol untuk menampilkan gambar bitmap, menggunakan
Fl_BoxdanNSButtonkustom - Label: label teks yang tidak dapat diedit, menggunakan
Fl_BoxdanNSTextField - ListBox: kontrol daftar dengan pilihan tunggal atau ganda, menggunakan
Fl_Select_Browser/Fl_Multi_BrowserdanNSTableView - ProgressBar: penampil progres untuk pekerjaan jangka panjang, menggunakan
Fl_ProgressdanNSProgressIndicator - Slider: input slider horizontal, menggunakan
Fl_SliderdanNSSlider - Spinner: input angka dengan tombol naik/turun, menggunakan
Fl_SpinnerdanNSTextField+NSStepper - TextField: input teks satu baris, menggunakan
Fl_InputdanNSTextField - TextEditor: editor teks multi-baris, menggunakan
Fl_Text_EditordanNSTextView - Window: kontrol jendela tingkat atas, menggunakan
Fl_WindowdanNSWindow
- Button: tombol untuk menjalankan aksi sederhana, menggunakan
- Ada juga kontrol dengan implementasi parsial atau belum diimplementasikan
- Dial: kontrol status melingkar dan berstatus ⚠️ implementasi parsial
- ComboBox: menu dropdown yang digabungkan dengan input teks dan belum dimulai
- Library kontrol Windows native
https://github.com/rodrigocfd/windigodisebut sebagai kandidat backend potensial di masa depan
1 komentar
Opini Hacker News
Ini wajib saya lihat. Saya sedang mencari cara sederhana untuk membuat tool pengembangan internal dengan Go, yang pada dasarnya hanya setingkat form dengan tombol dan field teks.
Saya juga pernah mencoba Gio, tetapi sulit dipahami, dan sekarang saya memakai wails yang jauh lebih saya sukai. Proyek ini juga menarik dan tampaknya layak ditelusuri.
Saya sangat menyarankan untuk benar-benar mengurangi arah “Lintas platform: Dengan memanfaatkan FLTK[1] dan Cocoa[2], Spot berjalan di Mac, Linux, BSD, dengan rencana dukungan Windows native di masa depan.”
Simpan saja pelajarannya agar fleksibilitas di masa depan tetap ada, tetapi sebaiknya kuasai dulu satu toolkit. GUI toolkit, binding GUI, dan GUI itu sendiri memang mudah sekali tenggelam dalam detail, dan kalau Anda dengan sukarela menanggung detail dari beberapa toolkit dasar sekaligus, besar kemungkinan akhirnya tidak ada satu toolkit pun yang benar-benar dikuasai.
Ada ungkapan “90% pertama adalah 90% pekerjaan, dan 10% sisanya adalah 90% lagi,” tetapi untuk GUI, itu pun terasa terlalu optimistis. 10% pertama adalah 90% pekerjaan, 10% berikutnya 10 kali lipatnya, dan 10% setelah itu juga 10 kali lipat lagi. Mencoba lintas platform bisa membuat Anda tercekik.
Saya tidak berharap Anda langsung setuju dengan pendapat ini sekarang, tetapi nanti ketika Anda menghadapi situasi di mana tiga toolkit memaksakan tiga cara yang saling bertentangan untuk menangani hal seperti rich text, semoga Anda mengizinkan diri sendiri untuk menyisakan hanya toolkit dasar yang paling baik didukung atau paling populer, dan membuang sisanya.
Saya sudah cukup lama mencari hal seperti ini di Go. Menurut saya Go punya peluang besar untuk memberikan developer experience yang bagus pada UI lintas platform karena proses build-nya sederhana.
Berdasarkan pengalaman, setengah dari penderitaan pengembangan lintas platform adalah mengelola kompleksitas build, dan Go hampir menghilangkan itu.
Namun ukuran default kontrol native berbeda-beda di tiap platform, jadi saya penasaran bagaimana layout lintas platform akan diselesaikan. Saya belum pernah melihat bagian ini diselesaikan dengan sangat baik di toolkit lintas platform lain. Bagaimanapun, semoga sukses.
Beberapa tahun lalu saya mencari hal seperti ini. Namun saya juga butuh dukungan Windows. Akhirnya saya beralih ke C++ untuk memakai wxWidgets, dan bisa mendapatkan binary kecil yang self-contained.
Saya terkesan melihat FLTK, meski merupakan toolkit native, mendukung zoom in/out seluruh aplikasi dengan Ctrl-+ dan Ctrl+- seperti browser. Dan berkat https://github.com/fltk-rs/fltk-theme?tab=readme-ov-file#wid..., kesan saya membaik tentang seberapa “native” tampilan FLTK bisa dibuat.
Terkait itu, baru-baru ini saya juga menemukan GoVCL https://z-kit.cc/en/ dan ingin mencobanya.
Spot “Hello World” yang self-contained berukuran 2.3MiB di Mac saya. Tidak cantik, tetapi cukup berfungsi bagi saya.
Saya penasaran apa keunggulan pendekatan pohon kontrol virtual dibandingkan cara memperbarui langsung kontrol yang ditampilkan kepada pengguna.
Anda harus menulis kode callback di mana-mana, dan setiap callback mungkin perlu memeriksa dengan hati-hati status terkini dari semua aktivitas lain sebelum memperbarui puluhan widget.
Dalam pendekatan reaktif, Anda menulis satu fungsi render yang mendeskripsikan antarmuka untuk state tertentu, lalu framework menangani kapan fungsi itu dipanggil dan input apa yang diberikan. Ini jauh lebih mudah dipahami, dan setelah memakai React, sulit untuk kembali, sehingga saya bereksperimen apakah hal serupa bisa dilakukan di Go.
Terlihat bagus. Saya penasaran apakah README bisa mencantumkan platform yang didukung.
Informasi seperti Windows, Linux, macOS, *BSD, Android, iOS, Web, Tizen rasanya cukup menarik.
Mungkin bisa ditulis seperti dokumentasi Flutter: https://docs.flutter.dev/reference/supported-platforms
Usahanya patut diapresiasi, tetapi lintas platform tanpa dukungan Windows?
Andai saya tahu ini 3 minggu lalu, atau andai dari riwayat commit proyek ini sudah ada saat itu. Sejak lama saya mengatakan bahwa React yang dip port ke Go atau framework mirip React untuk Go akan memberikan pengalaman pengembangan yang luar biasa, dan ini tampaknya sangat pas.
Saya dulu cukup tidak suka React.js sampai akhirnya tersadar lewat React.lua.
Akhirnya saya menemukan cara melakukan hal serupa hanya dengan
html/templatestandar Go, dan menulis detail implementasinya di sini: https://www.sheshbabu.com/posts/react-like-composition-using...Masalah besarnya adalah, kalau merilis untuk desktop, biasanya orang juga menginginkan versi web. Terutama jika itu bukan aplikasi yang sangat niche dan banyak berinteraksi dengan sistem operasi.
Atau Anda membutuhkan sesuatu yang menargetkan banyak platform, termasuk mobile.
Saya sudah cukup lama mencari, tetapi yang paling mendekati adalah Qt dan React Native, dan keduanya merupakan pilihan yang menyakitkan karena berbagai alasan.
FLTK mendukung Windows. Saya penasaran apakah mereka belum mendukung Windows karena berencana memakai solusi lain.
Namun tujuan saya, meski prioritasnya rendah, adalah mengimplementasikan backend berbasis Win32, dan langkah pertamanya sudah selesai: https://github.com/roblillack/spot/pull/4