Slight refactoring

This commit is contained in:
Ryan McGrath 2018-06-20 19:18:38 -04:00
parent 994d31ac3f
commit ea4d664511
No known key found for this signature in database
GPG key ID: 811674B62B666830
4 changed files with 100 additions and 82 deletions

View file

@ -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>"]

View file

@ -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",

View file

@ -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);

View file

@ -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);
} }
} }
} }