diff --git a/.circleci/config.yml b/.circleci/config.yml
index cf5487e91..0e5050e4f 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,7 +1,7 @@
version: 2
jobs:
- build:
+ core:
docker:
- image: rust:1
@@ -23,4 +23,100 @@ jobs:
key: target-cache
paths:
- ~/.cargo
- - ./target
\ No newline at end of file
+ - ./target
+
+ android:
+ docker:
+ - image: circleci/android:api-28
+
+ environment:
+ _JAVA_OPTIONS: "-Xmx3200m -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:ParallelGCThreads=2 -XX:ConcGCThreads=2 -XX:ParallelGCThreads=2 -Djava.util.concurrent.ForkJoinPool.common.parallelism=2"
+
+ steps:
+ - checkout
+ - restore_cache:
+ key: jars-{{ checksum "build.gradle" }}-{{ checksum "stretch/build.gradle" }}
+ - run: yes | sdkmanager --update || true
+ - run: cd android && ./gradlew androidDependencies --no-daemon --max-workers 2
+ - save_cache:
+ paths:
+ - ~/.gradle
+ key: jars-{{ checksum "build.gradle" }}-{{ checksum "stretch/build.gradle" }}
+ - run:
+ name: Setup emulator
+ command: sdkmanager "system-images;android-16;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-16;default;armeabi-v7a"
+ - run:
+ name: Launch emulator
+ command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel auto -verbose
+ background: true
+ - run:
+ name: Wait emulator
+ command: |
+ # wait for it to have booted
+ circle-android wait-for-boot
+ # unlock the emulator screen
+ sleep 30
+ adb shell input keyevent 82
+ - run:
+ name: Run tests
+ command: ./gradlew connectedAndroidTest
+ - store_artifacts:
+ path: stretch/build/reports
+ destination: reports
+ - store_test_results:
+ path: stretch/build/test-results
+
+workflows:
+ version: 2
+ test_all:
+ jobs:
+ - android
+ - core
+
+
+version: 2
+jobs:
+ build:
+ working_directory: ~/code
+ docker:
+ # Android the primary container
+ - image: circleci/android:api-26-alpha
+ environment:
+ JVM_OPTS: -Xmx3200m
+ steps:
+ - checkout
+ - restore_cache:
+ key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
+ - run:
+ name: Download Dependencies
+ command: ./gradlew androidDependencies
+ - save_cache:
+ paths:
+ - ~/.gradle
+ key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
+ - run:
+ name: Run UnitTest
+ command: ./gradlew testDemoDebugUnitTest
+ - run:
+ name: Setup emulator
+ command: sdkmanager "system-images;android-16;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-16;default;armeabi-v7a"
+ - run:
+ name: Launch emulator
+ command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel auto -verbose
+ background: true
+ - run:
+ name: Wait emulator
+ command: |
+ # wait for it to have booted
+ circle-android wait-for-boot
+ # unlock the emulator screen
+ sleep 30
+ adb shell input keyevent 82
+ - run:
+ name: Run EspressoTests
+ command: ./gradlew connectedDemoDebugAndroidTest
+ - store_artifacts:
+ path: app/build/reports
+ destination: reports
+ - store_test_results:
+ path: app/build/test-results
diff --git a/Cargo.toml b/Cargo.toml
index 7041f4984..abdddc80e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "stretch"
-version = "0.2.1"
+version = "0.2.2"
authors = ["Emil Sjölander <emil@visly.app>"]
edition = "2018"
include = ["src/**/*", "Cargo.toml"]
diff --git a/src/node.rs b/src/node.rs
index e9369b1a7..5221c464a 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -26,12 +26,12 @@ pub(crate) struct InternalNode {
pub struct Node(Rc<RefCell<InternalNode>>);
impl Node {
- pub fn new_leaf(style: Style, measure: Option<MeasureFunc>) -> Node {
+ pub fn new_leaf(style: Style, measure: MeasureFunc) -> Node {
Node(Rc::new(RefCell::new(InternalNode {
style,
parents: Vec::with_capacity(1),
children: Vec::with_capacity(0),
- measure,
+ measure: Some(measure),
layout_cache: None,
is_dirty: true,
})))
@@ -55,6 +55,11 @@ impl Node {
parent
}
+ pub fn set_measure(&mut self, measure: Option<MeasureFunc>) {
+ self.0.borrow_mut().measure = measure;
+ self.mark_dirty();
+ }
+
pub fn add_child(&mut self, child: &Node) {
child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
self.0.borrow_mut().children.push(Rc::clone(&child.0));
@@ -117,6 +122,11 @@ impl Node {
node.children.iter().map(|child| Node(Rc::clone(child))).collect()
}
+ pub fn child_count(&self) -> usize {
+ let node = self.0.borrow_mut();
+ node.children.len()
+ }
+
pub fn set_style(&mut self, style: Style) {
self.0.borrow_mut().style = style;
self.mark_dirty();
diff --git a/tests/measure.rs b/tests/measure.rs
index afed43f61..a5f3fb7f0 100644
--- a/tests/measure.rs
+++ b/tests/measure.rs
@@ -6,12 +6,12 @@ mod measure {
fn measure_root() {
let layout = stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)
.compute_layout(stretch::geometry::Size::undefined())
.unwrap();
@@ -26,12 +26,12 @@ mod measure {
stretch::style::Style { ..Default::default() },
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -53,12 +53,12 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -86,12 +86,12 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -124,12 +124,12 @@ mod measure {
),
&stretch::node::Node::new_leaf(
stretch::style::Style { flex_grow: 1.0, ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(10.0),
height: constraint.height.or_else(50.0),
})
- })),
+ }),
),
],
)
@@ -161,12 +161,12 @@ mod measure {
),
&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(50.0),
})
- })),
+ }),
),
],
)
@@ -198,11 +198,11 @@ mod measure {
),
&stretch::node::Node::new_leaf(
stretch::style::Style { flex_grow: 1.0, ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
let width = constraint.width.or_else(10.0);
let height = constraint.height.or_else(width * 2.0);
Ok(stretch::geometry::Size { width, height })
- })),
+ }),
),
],
)
@@ -235,11 +235,11 @@ mod measure {
),
&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
let width = constraint.width.or_else(100.0);
let height = constraint.height.or_else(width * 2.0);
Ok(stretch::geometry::Size { width, height })
- })),
+ }),
),
],
)
@@ -262,11 +262,11 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
let height = constraint.height.or_else(50.0);
let width = constraint.width.or_else(height);
Ok(stretch::geometry::Size { width, height })
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -288,12 +288,12 @@ mod measure {
},
..Default::default()
},
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -315,12 +315,12 @@ mod measure {
},
..Default::default()
},
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -355,12 +355,12 @@ mod measure {
flex_grow: 1.0,
..Default::default()
},
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(100.0),
height: constraint.height.or_else(100.0),
})
- })),
+ }),
),
],
)
@@ -385,12 +385,12 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(50.0),
height: constraint.height.or_else(50.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -412,12 +412,12 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { position_type: stretch::style::PositionType::Absolute, ..Default::default() },
- Some(Box::new(|constraint| {
+ Box::new(|constraint| {
Ok(stretch::geometry::Size {
width: constraint.width.or_else(50.0),
height: constraint.height.or_else(50.0),
})
- })),
+ }),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -439,7 +439,7 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { flex_grow: 1.0, ..Default::default() },
- Some(Box::new(|_| Ok(stretch::geometry::Size { width: 200.0, height: 200.0 }))),
+ Box::new(|_| Ok(stretch::geometry::Size { width: 200.0, height: 200.0 })),
)],
)
.compute_layout(stretch::geometry::Size::undefined())
@@ -460,13 +460,13 @@ mod measure {
stretch::style::Style { ..Default::default() },
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { ..Default::default() },
- Some(Box::new(move |constraint| {
+ Box::new(move |constraint| {
unsafe { (*num_measure_ptr) += 1 };
Ok(stretch::geometry::Size {
width: constraint.width.or_else(50.0),
height: constraint.height.or_else(50.0),
})
- })),
+ }),
)],
)],
)
@@ -488,7 +488,7 @@ mod measure {
},
vec![&stretch::node::Node::new_leaf(
stretch::style::Style { flex_grow: 1.0, ..Default::default() },
- Some(Box::new(|_| Err(Box::new("")))),
+ Box::new(|_| Err(Box::new(""))),
)],
)
.compute_layout(stretch::geometry::Size::undefined());
diff --git a/tests/node.rs b/tests/node.rs
index 1f29dddaf..ea35cb990 100644
--- a/tests/node.rs
+++ b/tests/node.rs
@@ -1,5 +1,6 @@
#[cfg(test)]
mod node {
+ use stretch::geometry::*;
use stretch::node::Node;
use stretch::style::*;
@@ -9,21 +10,30 @@ mod node {
let child2 = Node::new(Style::default(), vec![]);
let node = Node::new(Style::default(), vec![&child1, &child2]);
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
assert_eq!(node.children()[0], child1);
assert_eq!(node.children()[1], child2);
}
+ #[test]
+ fn set_measure() {
+ let mut node = Node::new_leaf(Style::default(), Box::new(|_| Ok(Size { width: 200.0, height: 200.0 })));
+ assert_eq!(node.compute_layout(Size::undefined()).unwrap().size.width, 200.0);
+
+ node.set_measure(Some(Box::new(|_| Ok(Size { width: 100.0, height: 100.0 }))));
+ assert_eq!(node.compute_layout(Size::undefined()).unwrap().size.width, 100.0);
+ }
+
#[test]
fn add_child() {
let mut node = Node::new(Style::default(), vec![]);
- assert_eq!(node.children().len(), 0);
+ assert_eq!(node.child_count(), 0);
node.add_child(&Node::new(Style::default(), vec![]));
- assert_eq!(node.children().len(), 1);
+ assert_eq!(node.child_count(), 1);
node.add_child(&Node::new(Style::default(), vec![]));
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
}
#[test]
@@ -32,14 +42,14 @@ mod node {
let child2 = Node::new(Style::default(), vec![]);
let mut node = Node::new(Style::default(), vec![&child1, &child2]);
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
node.remove_child(&child1);
- assert_eq!(node.children().len(), 1);
+ assert_eq!(node.child_count(), 1);
assert_eq!(node.children()[0], child2);
node.remove_child(&child2);
- assert_eq!(node.children().len(), 0);
+ assert_eq!(node.child_count(), 0);
}
#[test]
@@ -48,14 +58,14 @@ mod node {
let child2 = Node::new(Style::default(), vec![]);
let mut node = Node::new(Style::default(), vec![&child1, &child2]);
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
node.remove_child_at_index(0);
- assert_eq!(node.children().len(), 1);
+ assert_eq!(node.child_count(), 1);
assert_eq!(node.children()[0], child2);
node.remove_child_at_index(0);
- assert_eq!(node.children().len(), 0);
+ assert_eq!(node.child_count(), 0);
}
#[test]
@@ -64,11 +74,11 @@ mod node {
let child2 = Node::new(Style::default(), vec![]);
let mut node = Node::new(Style::default(), vec![&child1]);
- assert_eq!(node.children().len(), 1);
+ assert_eq!(node.child_count(), 1);
assert_eq!(node.children()[0], child1);
node.replace_child_at_index(0, &child2);
- assert_eq!(node.children().len(), 1);
+ assert_eq!(node.child_count(), 1);
assert_eq!(node.children()[0], child2);
}
@@ -78,7 +88,7 @@ mod node {
let child2 = Node::new(Style::default(), vec![]);
let mut node = Node::new(Style::default(), vec![&child1, &child2]);
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
assert_eq!(node.children()[0], child1);
assert_eq!(node.children()[1], child2);
@@ -86,7 +96,7 @@ mod node {
let child4 = Node::new(Style::default(), vec![]);
node.set_children(vec![&child3, &child4]);
- assert_eq!(node.children().len(), 2);
+ assert_eq!(node.child_count(), 2);
assert_eq!(node.children()[0], child3);
assert_eq!(node.children()[1], child4);
}