Slight refactoring
This commit is contained in:
parent
994d31ac3f
commit
ea4d664511
4 changed files with 100 additions and 82 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "layout"
|
name = "shinekit-layout-example"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Ryan McGrath <ryan@rymc.io>"]
|
authors = ["Ryan McGrath <ryan@rymc.io>"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"backgroundColor": {"r": 5, "g": 5, "b": 5},
|
"backgroundColor": {"r": 5, "g": 5, "b": 5},
|
||||||
"width": 200,
|
"width": 200,
|
||||||
|
"height": 400,
|
||||||
"top": "root.top",
|
"top": "root.top",
|
||||||
"left": "root.left",
|
"left": "root.left",
|
||||||
"bottom": "root.bottom"
|
"bottom": "root.bottom"
|
||||||
|
|
@ -19,6 +20,8 @@
|
||||||
|
|
||||||
"content": {
|
"content": {
|
||||||
"backgroundColor": {"r": 35, "g": 108, "b": 218},
|
"backgroundColor": {"r": 35, "g": 108, "b": 218},
|
||||||
|
"width": 100,
|
||||||
|
"height": 300,
|
||||||
"top": "root.top",
|
"top": "root.top",
|
||||||
"left": "sidebar.right",
|
"left": "sidebar.right",
|
||||||
"right": "root.right",
|
"right": "root.right",
|
||||||
|
|
|
||||||
|
|
@ -17,17 +17,12 @@ use cocoa::foundation::NSString;
|
||||||
|
|
||||||
use shinekit::color::Color;
|
use shinekit::color::Color;
|
||||||
use shinekit::util::empty_frame;
|
use shinekit::util::empty_frame;
|
||||||
use shinekit::layout::{Layout, add_autolayout_ivars};
|
|
||||||
|
|
||||||
pub struct Text {
|
pub struct Label;
|
||||||
pub backing_node: Id<Object>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
impl Label {
|
||||||
impl Text {
|
pub fn named(name: &str) -> Self {
|
||||||
pub fn new() -> Self {
|
View::named_of_kind_with_backing_node(name, ViewKind::Label, unsafe {
|
||||||
Text {
|
|
||||||
backing_node: unsafe {
|
|
||||||
let alloc: id = msg_send![register_text_class(), alloc];
|
let alloc: id = msg_send![register_text_class(), alloc];
|
||||||
let view: id = msg_send![alloc, initWithFrame:empty_frame()];
|
let view: id = msg_send![alloc, initWithFrame:empty_frame()];
|
||||||
msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||||
|
|
@ -43,6 +38,15 @@ impl Text {
|
||||||
msg_send![cell, setWraps:YES];
|
msg_send![cell, setWraps:YES];
|
||||||
msg_send![cell, setLineBreakMode:0];
|
msg_send![cell, setLineBreakMode:0];
|
||||||
Id::from_ptr(view)
|
Id::from_ptr(view)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
impl Text {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Text {
|
||||||
|
backing_node: unsafe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -68,18 +72,13 @@ impl Text {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Layout for Text {
|
|
||||||
fn get_root_backing_node(&self) -> &Object { &*self.backing_node }
|
|
||||||
fn set_constraint_ivar(&mut self, ivar: &str, constraint: id) { unsafe { self.backing_node.set_ivar(ivar, constraint); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_text_class() -> *const Class {
|
fn register_text_class() -> *const Class {
|
||||||
static mut text_class: *const Class = 0 as *const Class;
|
static mut text_class: *const Class = 0 as *const Class;
|
||||||
static INIT: Once = ONCE_INIT;
|
static INIT: Once = ONCE_INIT;
|
||||||
|
|
||||||
INIT.call_once(|| unsafe {
|
INIT.call_once(|| unsafe {
|
||||||
let superclass = Class::get("NSTextField").unwrap();
|
let superclass = Class::get("NSTextField").unwrap();
|
||||||
let mut decl = ClassDecl::new("shinekitTextLabel", superclass).unwrap();
|
let mut decl = ClassDecl::new("ShineKitLabel", superclass).unwrap();
|
||||||
//decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern fn(&Object, _) -> BOOL);
|
//decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern fn(&Object, _) -> BOOL);
|
||||||
//decl.add_method(sel!(updateLayer), update_layer as extern fn(&Object, _));
|
//decl.add_method(sel!(updateLayer), update_layer as extern fn(&Object, _));
|
||||||
add_autolayout_ivars(&mut decl);
|
add_autolayout_ivars(&mut decl);
|
||||||
106
src/view.rs
106
src/view.rs
|
|
@ -33,38 +33,35 @@ pub struct View {
|
||||||
pub subviews: Vec<View>
|
pub subviews: Vec<View>
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_view_backing_node() -> Id<Object> {
|
impl View {
|
||||||
|
pub fn named_of_kind_with_backing_node(name: &str, kind: ViewKind, backing_node: Id<Object>) -> Self {
|
||||||
|
View {
|
||||||
|
name: name.into(),
|
||||||
|
kind: kind,
|
||||||
|
backing_node: backing_node,
|
||||||
|
subviews: vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn named(name: &str) -> Self {
|
||||||
|
View::named_of_kind_with_backing_node(name, ViewKind::View, unsafe {
|
||||||
let alloc: id = msg_send![register_view_class(), alloc];
|
let alloc: id = msg_send![register_view_class(), alloc];
|
||||||
let view: id = msg_send![alloc, initWithFrame:empty_frame()];
|
let view: id = msg_send![alloc, initWithFrame:empty_frame()];
|
||||||
msg_send![view, setWantsLayer:YES];
|
msg_send![view, setWantsLayer:YES];
|
||||||
msg_send![view, setLayerContentsRedrawPolicy:1];
|
msg_send![view, setLayerContentsRedrawPolicy:1];
|
||||||
msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||||
Id::from_ptr(view)
|
Id::from_ptr(view)
|
||||||
}
|
})
|
||||||
|
|
||||||
impl View {
|
|
||||||
pub fn named(name: &str) -> Self {
|
|
||||||
View {
|
|
||||||
name: name.into(),
|
|
||||||
kind: ViewKind::View,
|
|
||||||
backing_node: unsafe { create_view_backing_node() },
|
|
||||||
subviews: vec![]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subviews(self, views: Vec<View>) -> Self {
|
pub fn subviews(self, views: Vec<View>) -> Self {
|
||||||
let mut subviews = vec![];
|
let mut subviews = vec![];
|
||||||
unsafe {
|
|
||||||
for view in views.into_iter() {
|
for view in views.into_iter() {
|
||||||
msg_send![&*self.backing_node, addSubview:&*view.backing_node];
|
unsafe { msg_send![&*self.backing_node, addSubview:&*view.backing_node]; }
|
||||||
subviews.push(view);
|
subviews.push(view);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
View {
|
View { subviews: subviews, ..self }
|
||||||
subviews: subviews,
|
|
||||||
..self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_background_color(&mut self, color: &Color) {
|
pub fn set_background_color(&mut self, color: &Color) {
|
||||||
|
|
@ -74,18 +71,13 @@ impl View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_styles(&mut self, styles: &mut Map<String, Value>) {
|
|
||||||
let bg_color = Color::from_json(&styles[&self.name]["backgroundColor"]);
|
|
||||||
self.set_background_color(&bg_color);
|
|
||||||
|
|
||||||
for view in &mut self.subviews {
|
|
||||||
view.apply_styles(styles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_root_backing_node(&self) -> &Object { &*self.backing_node }
|
pub fn get_root_backing_node(&self) -> &Object { &*self.backing_node }
|
||||||
pub fn get_subviews(&self) -> &Vec<View> { &self.subviews }
|
pub fn get_subviews(&self) -> &Vec<View> { &self.subviews }
|
||||||
pub fn set_constraint_ivar(&mut self, ivar: &str, constraint: id) { unsafe { self.backing_node.set_ivar(ivar, constraint); } }
|
pub fn set_ivar(&mut self, ivar: &str, constraint: id) {
|
||||||
|
unsafe {
|
||||||
|
self.backing_node.set_ivar(ivar, constraint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_subview(&self, view: &View) {
|
pub fn add_subview(&self, view: &View) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -100,19 +92,19 @@ impl View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn width(&mut self, width: i32) {
|
pub fn set_width(&mut self, width: f64) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let anchor: id = msg_send![self.get_root_backing_node(), widthAnchor];
|
let anchor: id = msg_send![self.get_root_backing_node(), widthAnchor];
|
||||||
let constraint: id = msg_send![anchor, constraintEqualToConstant:width as f64];
|
let constraint: id = msg_send![anchor, constraintEqualToConstant:width];
|
||||||
self.set_constraint_ivar("shinekitConstraintWidth", constraint);
|
self.set_ivar("shinekitConstraintWidth", constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn height(&mut self, height: i32) {
|
pub fn set_height(&mut self, height: f64) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let anchor: id = msg_send![self.get_root_backing_node(), heightAnchor];
|
let anchor: id = msg_send![self.get_root_backing_node(), heightAnchor];
|
||||||
let constraint: id = msg_send![anchor, constraintEqualToConstant:height as f64];
|
let constraint: id = msg_send![anchor, constraintEqualToConstant:height];
|
||||||
self.set_constraint_ivar("shinekitConstraintHeight", constraint);
|
self.set_ivar("shinekitConstraintHeight", constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,7 +113,7 @@ impl View {
|
||||||
let top_anchor: id = msg_send![self.get_root_backing_node(), topAnchor];
|
let top_anchor: id = msg_send![self.get_root_backing_node(), topAnchor];
|
||||||
let view_top_anchor: id = msg_send![view.get_root_backing_node(), topAnchor];
|
let view_top_anchor: id = msg_send![view.get_root_backing_node(), topAnchor];
|
||||||
let constraint: id = msg_send![top_anchor, constraintEqualToAnchor:view_top_anchor constant:margin as f64];
|
let constraint: id = msg_send![top_anchor, constraintEqualToAnchor:view_top_anchor constant:margin as f64];
|
||||||
self.set_constraint_ivar("shinekitConstraintTop", constraint);
|
self.set_ivar("shinekitConstraintTop", constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +122,7 @@ impl View {
|
||||||
let leading_anchor: id = msg_send![self.get_root_backing_node(), leadingAnchor];
|
let leading_anchor: id = msg_send![self.get_root_backing_node(), leadingAnchor];
|
||||||
let view_leading_anchor: id = msg_send![view.get_root_backing_node(), leadingAnchor];
|
let view_leading_anchor: id = msg_send![view.get_root_backing_node(), leadingAnchor];
|
||||||
let constraint: id = msg_send![leading_anchor, constraintEqualToAnchor:view_leading_anchor constant:margin as f64];
|
let constraint: id = msg_send![leading_anchor, constraintEqualToAnchor:view_leading_anchor constant:margin as f64];
|
||||||
self.set_constraint_ivar("shinekitConstraintLeading", constraint);
|
self.set_ivar("shinekitConstraintLeading", constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,7 +132,7 @@ impl View {
|
||||||
let trailing_anchor: id = msg_send![self.get_root_backing_node(), trailingAnchor];
|
let trailing_anchor: id = msg_send![self.get_root_backing_node(), trailingAnchor];
|
||||||
let view_trailing_anchor: id = msg_send![view.get_root_backing_node(), trailingAnchor];
|
let view_trailing_anchor: id = msg_send![view.get_root_backing_node(), trailingAnchor];
|
||||||
let constraint: id = msg_send![trailing_anchor, constraintEqualToAnchor:view_trailing_anchor constant:m];
|
let constraint: id = msg_send![trailing_anchor, constraintEqualToAnchor:view_trailing_anchor constant:m];
|
||||||
self.set_constraint_ivar("shinekitConstraintTrailing", constraint);
|
self.set_ivar("shinekitConstraintTrailing", constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,13 +142,12 @@ impl View {
|
||||||
let bottom_anchor: id = msg_send![self.get_root_backing_node(), bottomAnchor];
|
let bottom_anchor: id = msg_send![self.get_root_backing_node(), bottomAnchor];
|
||||||
let view_bottom_anchor: id = msg_send![view.get_root_backing_node(), bottomAnchor];
|
let view_bottom_anchor: id = msg_send![view.get_root_backing_node(), bottomAnchor];
|
||||||
let constraint: id = msg_send![bottom_anchor, constraintEqualToAnchor:view_bottom_anchor constant:m];
|
let constraint: id = msg_send![bottom_anchor, constraintEqualToAnchor:view_bottom_anchor constant:m];
|
||||||
self.set_constraint_ivar("shinekitConstraintBottom", constraint);
|
self.set_ivar("shinekitConstraintBottom", constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn activate_constraints(&self) {
|
pub fn activate_constraints(&self) {
|
||||||
unsafe {
|
let mut constraints: Vec<id> = vec![];
|
||||||
let mut anchors: Vec<id> = vec![];
|
|
||||||
|
|
||||||
let ivars = [
|
let ivars = [
|
||||||
"shinekitConstraintWidth", "shinekitConstraintHeight",
|
"shinekitConstraintWidth", "shinekitConstraintHeight",
|
||||||
|
|
@ -164,14 +155,39 @@ impl View {
|
||||||
"shinekitConstraintTrailing", "shinekitConstraintBottom"
|
"shinekitConstraintTrailing", "shinekitConstraintBottom"
|
||||||
];
|
];
|
||||||
|
|
||||||
let view = self.get_root_backing_node();
|
|
||||||
for ivar in &ivars {
|
for ivar in &ivars {
|
||||||
let constraint: id = *view.get_ivar(ivar);
|
let constraint: id;
|
||||||
if constraint != nil { anchors.push(constraint); }
|
unsafe { constraint = *self.backing_node.get_ivar(ivar); }
|
||||||
|
|
||||||
|
if constraint != nil {
|
||||||
|
constraints.push(constraint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let constraints = NSArray::arrayWithObjects(nil, &anchors);
|
if constraints.len() > 0 {
|
||||||
msg_send![class("NSLayoutConstraint"), activateConstraints:constraints];
|
unsafe {
|
||||||
|
let bundle = NSArray::arrayWithObjects(nil, &constraints);
|
||||||
|
msg_send![class("NSLayoutConstraint"), activateConstraints:bundle];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_styles(&mut self, styles: &mut Map<String, Value>) {
|
||||||
|
let bg_color = Color::from_json(&styles[&self.name]["backgroundColor"]);
|
||||||
|
self.set_background_color(&bg_color);
|
||||||
|
|
||||||
|
match styles[&self.name]["width"].as_f64() {
|
||||||
|
Some(width) => self.set_width(width),
|
||||||
|
None => ()
|
||||||
|
}
|
||||||
|
|
||||||
|
match styles[&self.name]["height"].as_f64() {
|
||||||
|
Some(width) => self.set_width(width),
|
||||||
|
None => ()
|
||||||
|
}
|
||||||
|
|
||||||
|
for view in &mut self.subviews {
|
||||||
|
view.apply_styles(styles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Reference in a new issue