Ongoing work on supporting GTK, had to rework some concepts due to the way gtk-rs works.
This commit is contained in:
parent
f15cf258af
commit
0d8a14ce67
20 changed files with 378 additions and 301 deletions
19
gtk/Cargo.toml
Normal file
19
gtk/Cargo.toml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "alchemy-gtkrs"
|
||||
description = "GTK bindings for Alchemy, a cross-platform GUI framework written in Rust."
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
authors = ["Ryan McGrath <ryan@rymc.io>"]
|
||||
license = "MPL-2.0+"
|
||||
repository = "https://github.com/ryanmcgrath/alchemy"
|
||||
categories = ["gui", "rendering::engine", "multimedia"]
|
||||
keywords = ["gui", "gtk", "react"]
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
||||
[dependencies]
|
||||
alchemy-lifecycle = { version = "0.1", path = "../lifecycle", features = ["gtkrs"] }
|
||||
alchemy-styles = { version = "0.1", path = "../styles" }
|
||||
gtk = { version = "0.6.0", features = ["v3_16"] }
|
||||
gio = "0.6.0"
|
||||
44
gtk/src/app.rs
Normal file
44
gtk/src/app.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//! A wrapper for `Application` on GTK-based systems. If you opt in to the `gtkrs` feature on
|
||||
//! Alchemy, this will loop system-level application events back to your `AppDelegate`.
|
||||
|
||||
use std::env;
|
||||
|
||||
use gio::{ApplicationFlags};
|
||||
use gtk::{Application};
|
||||
use gio::prelude::{ApplicationExt, ApplicationExtManual};
|
||||
|
||||
use alchemy_lifecycle::traits::AppDelegate;
|
||||
|
||||
/// A wrapper for `gtk::Application`.
|
||||
pub struct App {
|
||||
pub inner: Application
|
||||
}
|
||||
|
||||
impl App {
|
||||
/// Creates a `gtk::Application` instance, and wires up appropriate lifecycle handlers to loop
|
||||
/// back to the `AppDelegate`.
|
||||
pub fn new<T: AppDelegate + 'static>(parent_app_ptr: *const T) -> Self {
|
||||
let inner = Application::new("lol.my.app", ApplicationFlags::FLAGS_NONE)
|
||||
.expect("Could not create GTK Application instance!");
|
||||
|
||||
inner.connect_activate(move |app| {
|
||||
println!("ACTIVATED");
|
||||
let app = parent_app_ptr as *mut T;
|
||||
unsafe {
|
||||
(*app).did_finish_launching();
|
||||
}
|
||||
println!("HELLO");
|
||||
});
|
||||
|
||||
println!("MADE");
|
||||
App {
|
||||
inner: inner
|
||||
}
|
||||
}
|
||||
|
||||
/// Kicks off the Run Loop for the Application instance. This blocks when called.
|
||||
pub fn run(&self) {
|
||||
println!("RUNNING");
|
||||
self.inner.run(&env::args().collect::<Vec<_>>());
|
||||
}
|
||||
}
|
||||
22
gtk/src/lib.rs
Normal file
22
gtk/src/lib.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//! This crate provides a GTK backend for Alchemy, the Rust GUI framework.
|
||||
//! This means that, on GTK-based systems, you'll be using native views
|
||||
//! and other assorted controls. Where possible, it attempts to opt into
|
||||
//! smoother rendering paths.
|
||||
//!
|
||||
//! # License
|
||||
//!
|
||||
//! Copyright 2019 Ryan McGrath. See the license files included in the root repository
|
||||
//! for more information, along with credit to applicable parties for who this project
|
||||
//! would not have happened.
|
||||
//!
|
||||
//! # Code of Conduct
|
||||
//!
|
||||
//! Please note that this project is released with a [Contributor Code of
|
||||
//! Conduct][coc]. By participating in this project you agree to abide by its terms.
|
||||
//!
|
||||
//! [coc]: https://www.contributor-covenant.org/version/1/4/code-of-conduct
|
||||
|
||||
pub mod app;
|
||||
pub mod text;
|
||||
pub mod view;
|
||||
pub mod window;
|
||||
47
gtk/src/text.rs
Normal file
47
gtk/src/text.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
//! This wraps NTextField on macOS, and configures it to act like a label
|
||||
//! with standard behavior that most users would expect.
|
||||
|
||||
use alchemy_styles::{Color, Layout, Appearance};
|
||||
|
||||
use alchemy_lifecycle::traits::PlatformSpecificNodeType;
|
||||
|
||||
static ALCHEMY_DELEGATE: &str = "alchemyDelegate";
|
||||
|
||||
/// A wrapper for `NSText`. This holds retained pointers for the Objective-C
|
||||
/// runtime - namely, the view itself, and associated things such as background
|
||||
/// colors and so forth.
|
||||
#[derive(Debug)]
|
||||
pub struct Text {
|
||||
}
|
||||
|
||||
impl Text {
|
||||
/// Allocates a new `NSTextField` on the Objective-C side, ensuring that things like coordinate
|
||||
/// flipping occur (macOS still uses (0,0) as lower-left by default), and opting in to layer
|
||||
/// backed views for smoother scrolling.
|
||||
pub fn new() -> Text {
|
||||
Text {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a pointer to the underlying Objective-C view. The pointer is not mutable; however,
|
||||
/// you can send messages to it (unsafely).
|
||||
pub fn borrow_native_backing_node(&self) -> PlatformSpecificNodeType {
|
||||
()
|
||||
}
|
||||
|
||||
/// Appends a child NSText (or subclassed type) to this view.
|
||||
pub fn append_child(&mut self, child: PlatformSpecificNodeType) {
|
||||
}
|
||||
|
||||
/// Given a `&Style`, will set the frame, background color, borders and so forth. It then
|
||||
/// calls `setNeedsDisplay:YES` on the Objective-C side, so that Cocoa will re-render this
|
||||
/// view.
|
||||
pub fn apply_styles(&mut self, appearance: &Appearance, layout: &Layout) {
|
||||
}
|
||||
|
||||
pub fn set_text(&mut self, text: String) {
|
||||
}
|
||||
|
||||
pub fn render(&mut self) {
|
||||
}
|
||||
}
|
||||
38
gtk/src/view.rs
Normal file
38
gtk/src/view.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
//! Implements a View Component struct. The most common
|
||||
//! basic building block of any app. Wraps NSView on macOS.
|
||||
|
||||
use alchemy_styles::{Appearance, Color, Layout};
|
||||
|
||||
use alchemy_lifecycle::traits::PlatformSpecificNodeType;
|
||||
|
||||
/// A wrapper for `NSView`. This holds retained pointers for the Objective-C
|
||||
/// runtime - namely, the view itself, and associated things such as background
|
||||
/// colors and so forth.
|
||||
#[derive(Debug)]
|
||||
pub struct View {}
|
||||
|
||||
impl View {
|
||||
/// Allocates a new `NSView` on the Objective-C side, ensuring that things like coordinate
|
||||
/// flipping occur (macOS still uses (0,0) as lower-left by default), and opting in to layer
|
||||
/// backed views for smoother scrolling.
|
||||
pub fn new() -> View {
|
||||
View {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a pointer to the underlying Objective-C view. The pointer is not mutable; however,
|
||||
/// you can send messages to it (unsafely).
|
||||
pub fn borrow_native_backing_node(&self) -> PlatformSpecificNodeType {
|
||||
()
|
||||
}
|
||||
|
||||
/// Appends a child NSView (or subclassed type) to this view.
|
||||
pub fn append_child(&mut self, child: PlatformSpecificNodeType) {
|
||||
}
|
||||
|
||||
/// Given a `&Style`, will set the frame, background color, borders and so forth. It then
|
||||
/// calls `setNeedsDisplay:YES` on the Objective-C side, so that Cocoa will re-render this
|
||||
/// view.
|
||||
pub fn apply_styles(&mut self, appearance: &Appearance, layout: &Layout) {
|
||||
}
|
||||
}
|
||||
73
gtk/src/window.rs
Normal file
73
gtk/src/window.rs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
//! Implements a `gtk::ApplicationWindow` wrapper for GTK-based systems.
|
||||
//! This also handles looping back lifecycle events, such as window
|
||||
//! resizing or close events.
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
use gtk::{
|
||||
ContainerExt,
|
||||
GtkWindowExt, WidgetExt,
|
||||
Window as GtkWindow, WindowType
|
||||
};
|
||||
|
||||
use alchemy_lifecycle::traits::WindowDelegate;
|
||||
use alchemy_styles::Appearance;
|
||||
|
||||
/// A wrapper for `NSWindow`. Holds (retains) pointers for the Objective-C runtime
|
||||
/// where our `NSWindow` and associated delegate live.
|
||||
pub struct Window {
|
||||
pub inner: GtkWindow
|
||||
}
|
||||
|
||||
impl Window {
|
||||
/// Creates a new `NSWindow` instance, configures it appropriately (e.g, titlebar appearance),
|
||||
/// injects an `NSObject` delegate wrapper, and retains the necessary Objective-C runtime
|
||||
/// pointers.
|
||||
pub fn new<T: WindowDelegate>(content_view: (), app_ptr: *const RefCell<T>) -> Window {
|
||||
Window {
|
||||
inner: GtkWindow::new(WindowType::Toplevel)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_title(&mut self, title: &str) {
|
||||
self.inner.set_title(title);
|
||||
}
|
||||
|
||||
pub fn set_dimensions(&mut self, x: f64, y: f64, width: f64, height: f64) {
|
||||
self.inner.set_position(gtk::WindowPosition::Center);
|
||||
self.inner.set_default_size(width as i32, height as i32);
|
||||
}
|
||||
|
||||
/// Normally used for setting platform-specific styles; on macOS we choose not to do this and
|
||||
/// just have the content view handle the background color, as calling window
|
||||
/// setBackgroundColor causes some notable lag on resizing.
|
||||
pub fn apply_styles(&mut self, _appearance: &Appearance) { }
|
||||
|
||||
/// On macOS, calling `show()` is equivalent to calling `makeKeyAndOrderFront`. This is the
|
||||
/// most common use case, hence why this method was chosen - if you want or need something
|
||||
/// else, feel free to open an issue to discuss.
|
||||
///
|
||||
/// You should never be calling this yourself, mind you - Alchemy core handles this for you.
|
||||
pub fn show(&self) {
|
||||
let button = gtk::Button::new_with_label("Click me!");
|
||||
self.inner.add(&button);
|
||||
self.inner.show_all();
|
||||
}
|
||||
|
||||
/// On macOS, calling `close()` is equivalent to calling... well, `close`. It closes the
|
||||
/// window.
|
||||
///
|
||||
/// I dunno what else to say here, lol.
|
||||
///
|
||||
/// You should never be calling this yourself, mind you - Alchemy core handles this for you.
|
||||
pub fn close(&self) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
/// When a Window is dropped on the Rust side, we want to ensure that we break the delegate
|
||||
/// link on the Objective-C side. While this shouldn't actually be an issue, I'd rather be
|
||||
/// safer than sorry.
|
||||
fn drop(&mut self) {
|
||||
}
|
||||
}
|
||||
Reference in a new issue