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]
|
||||
name = "layout"
|
||||
name = "shinekit-layout-example"
|
||||
version = "0.1.0"
|
||||
authors = ["Ryan McGrath <ryan@rymc.io>"]
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
"sidebar": {
|
||||
"backgroundColor": {"r": 5, "g": 5, "b": 5},
|
||||
"width": 200,
|
||||
"height": 400,
|
||||
"top": "root.top",
|
||||
"left": "root.left",
|
||||
"bottom": "root.bottom"
|
||||
|
|
@ -19,6 +20,8 @@
|
|||
|
||||
"content": {
|
||||
"backgroundColor": {"r": 35, "g": 108, "b": 218},
|
||||
"width": 100,
|
||||
"height": 300,
|
||||
"top": "root.top",
|
||||
"left": "sidebar.right",
|
||||
"right": "root.right",
|
||||
|
|
|
|||
|
|
@ -17,10 +17,29 @@ use cocoa::foundation::NSString;
|
|||
|
||||
use shinekit::color::Color;
|
||||
use shinekit::util::empty_frame;
|
||||
use shinekit::layout::{Layout, add_autolayout_ivars};
|
||||
|
||||
pub struct Text {
|
||||
pub backing_node: Id<Object>
|
||||
pub struct Label;
|
||||
|
||||
impl Label {
|
||||
pub fn named(name: &str) -> Self {
|
||||
View::named_of_kind_with_backing_node(name, ViewKind::Label, unsafe {
|
||||
let alloc: id = msg_send![register_text_class(), alloc];
|
||||
let view: id = msg_send![alloc, initWithFrame:empty_frame()];
|
||||
msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||
msg_send![view, setEditable:NO];
|
||||
msg_send![view, setBezeled:NO];
|
||||
msg_send![view, setBordered:NO];
|
||||
msg_send![view, setDrawsBackground:YES];
|
||||
msg_send![view, setAllowsEditingTextAttributes:NO];
|
||||
msg_send![view, setContentCompressionResistancePriority:250 forOrientation:0];
|
||||
|
||||
let cell: id = msg_send![view, cell];
|
||||
msg_send![cell, setUsesSingleLineMode:NO];
|
||||
msg_send![cell, setWraps:YES];
|
||||
msg_send![cell, setLineBreakMode:0];
|
||||
Id::from_ptr(view)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -28,21 +47,6 @@ impl Text {
|
|||
pub fn new() -> Self {
|
||||
Text {
|
||||
backing_node: unsafe {
|
||||
let alloc: id = msg_send![register_text_class(), alloc];
|
||||
let view: id = msg_send![alloc, initWithFrame:empty_frame()];
|
||||
msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||
msg_send![view, setEditable:NO];
|
||||
msg_send![view, setBezeled:NO];
|
||||
msg_send![view, setBordered:NO];
|
||||
msg_send![view, setDrawsBackground:YES];
|
||||
msg_send![view, setAllowsEditingTextAttributes:NO];
|
||||
msg_send![view, setContentCompressionResistancePriority:250 forOrientation:0];
|
||||
|
||||
let cell: id = msg_send![view, cell];
|
||||
msg_send![cell, setUsesSingleLineMode:NO];
|
||||
msg_send![cell, setWraps:YES];
|
||||
msg_send![cell, setLineBreakMode:0];
|
||||
Id::from_ptr(view)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
static mut text_class: *const Class = 0 as *const Class;
|
||||
static INIT: Once = ONCE_INIT;
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
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!(updateLayer), update_layer as extern fn(&Object, _));
|
||||
add_autolayout_ivars(&mut decl);
|
||||
124
src/view.rs
124
src/view.rs
|
|
@ -33,38 +33,35 @@ pub struct View {
|
|||
pub subviews: Vec<View>
|
||||
}
|
||||
|
||||
unsafe fn create_view_backing_node() -> Id<Object> {
|
||||
let alloc: id = msg_send![register_view_class(), alloc];
|
||||
let view: id = msg_send![alloc, initWithFrame:empty_frame()];
|
||||
msg_send![view, setWantsLayer:YES];
|
||||
msg_send![view, setLayerContentsRedrawPolicy:1];
|
||||
msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||
Id::from_ptr(view)
|
||||
}
|
||||
|
||||
impl View {
|
||||
pub fn named(name: &str) -> Self {
|
||||
pub fn named_of_kind_with_backing_node(name: &str, kind: ViewKind, backing_node: Id<Object>) -> Self {
|
||||
View {
|
||||
name: name.into(),
|
||||
kind: ViewKind::View,
|
||||
backing_node: unsafe { create_view_backing_node() },
|
||||
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 view: id = msg_send![alloc, initWithFrame:empty_frame()];
|
||||
msg_send![view, setWantsLayer:YES];
|
||||
msg_send![view, setLayerContentsRedrawPolicy:1];
|
||||
msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||
Id::from_ptr(view)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn subviews(self, views: Vec<View>) -> Self {
|
||||
let mut subviews = vec![];
|
||||
unsafe {
|
||||
for view in views.into_iter() {
|
||||
msg_send![&*self.backing_node, addSubview:&*view.backing_node];
|
||||
subviews.push(view);
|
||||
}
|
||||
for view in views.into_iter() {
|
||||
unsafe { msg_send![&*self.backing_node, addSubview:&*view.backing_node]; }
|
||||
subviews.push(view);
|
||||
}
|
||||
|
||||
View {
|
||||
subviews: subviews,
|
||||
..self
|
||||
}
|
||||
View { subviews: subviews, ..self }
|
||||
}
|
||||
|
||||
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_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) {
|
||||
unsafe {
|
||||
|
|
@ -100,19 +92,19 @@ impl View {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn width(&mut self, width: i32) {
|
||||
pub fn set_width(&mut self, width: f64) {
|
||||
unsafe {
|
||||
let anchor: id = msg_send![self.get_root_backing_node(), widthAnchor];
|
||||
let constraint: id = msg_send![anchor, constraintEqualToConstant:width as f64];
|
||||
self.set_constraint_ivar("shinekitConstraintWidth", constraint);
|
||||
let constraint: id = msg_send![anchor, constraintEqualToConstant:width];
|
||||
self.set_ivar("shinekitConstraintWidth", constraint);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height(&mut self, height: i32) {
|
||||
pub fn set_height(&mut self, height: f64) {
|
||||
unsafe {
|
||||
let anchor: id = msg_send![self.get_root_backing_node(), heightAnchor];
|
||||
let constraint: id = msg_send![anchor, constraintEqualToConstant:height as f64];
|
||||
self.set_constraint_ivar("shinekitConstraintHeight", constraint);
|
||||
let constraint: id = msg_send![anchor, constraintEqualToConstant:height];
|
||||
self.set_ivar("shinekitConstraintHeight", constraint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +113,7 @@ impl View {
|
|||
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 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 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];
|
||||
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 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];
|
||||
self.set_constraint_ivar("shinekitConstraintTrailing", constraint);
|
||||
self.set_ivar("shinekitConstraintTrailing", constraint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -150,28 +142,52 @@ impl View {
|
|||
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 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) {
|
||||
unsafe {
|
||||
let mut anchors: Vec<id> = vec![];
|
||||
let mut constraints: Vec<id> = vec![];
|
||||
|
||||
let ivars = [
|
||||
"shinekitConstraintWidth", "shinekitConstraintHeight",
|
||||
"shinekitConstraintTop", "shinekitConstraintLeading",
|
||||
"shinekitConstraintTrailing", "shinekitConstraintBottom"
|
||||
];
|
||||
let ivars = [
|
||||
"shinekitConstraintWidth", "shinekitConstraintHeight",
|
||||
"shinekitConstraintTop", "shinekitConstraintLeading",
|
||||
"shinekitConstraintTrailing", "shinekitConstraintBottom"
|
||||
];
|
||||
|
||||
let view = self.get_root_backing_node();
|
||||
for ivar in &ivars {
|
||||
let constraint: id = *view.get_ivar(ivar);
|
||||
if constraint != nil { anchors.push(constraint); }
|
||||
for ivar in &ivars {
|
||||
let constraint: id;
|
||||
unsafe { constraint = *self.backing_node.get_ivar(ivar); }
|
||||
|
||||
if constraint != nil {
|
||||
constraints.push(constraint);
|
||||
}
|
||||
}
|
||||
|
||||
let constraints = NSArray::arrayWithObjects(nil, &anchors);
|
||||
msg_send![class("NSLayoutConstraint"), activateConstraints:constraints];
|
||||
if constraints.len() > 0 {
|
||||
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