Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Java bindings #705

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c1bb7a9
wip: java bindings
adjabaev Aug 19, 2024
21ec83d
Pretty much usable (there are missing functions such as remove and so…
adjabaev Aug 20, 2024
65db9eb
rust fmt formatting (did i figure it out?)
adjabaev Aug 20, 2024
4fe722b
Fix Clippy issues
adjabaev Aug 20, 2024
9891bbb
java: turn into a maven project
adjabaev Aug 20, 2024
47bea2e
java: implement a few tests to ensure everything is working as intended
adjabaev Aug 21, 2024
3eabd6c
rust-java: Add most of methods in TaffyTree
adjabaev Aug 21, 2024
587c810
rust: rustfmt
adjabaev Aug 21, 2024
81dcdcd
java: utility
adjabaev Aug 21, 2024
b53ea74
rust: fix signatures
adjabaev Aug 21, 2024
a0dab92
rust-java: remove Taffy from classes & change signatures
adjabaev Aug 21, 2024
d778ff2
enums: enum generator (just to collect feedback)
adjabaev Aug 26, 2024
6d1beb2
enums: fix index parameter as we can get it with ordinal()
adjabaev Aug 26, 2024
71064b0
enums: write files to enum folder
adjabaev Aug 26, 2024
32865ee
enums: use autogenerated files
adjabaev Aug 26, 2024
1fd2c5b
enums: update refs
adjabaev Aug 27, 2024
8bf25f1
java: readded first example for reference
adjabaev Aug 28, 2024
5bae96d
java: add nested and somewhat tweak toString's
adjabaev Aug 28, 2024
9b412c8
java: gap & related util
adjabaev Aug 28, 2024
cbdb98c
rust: fix enum field stuff
adjabaev Aug 28, 2024
114a279
rust/ java: wip - more complex examples
adjabaev Aug 29, 2024
560fd19
genenums: move to to scripts folder
adjabaev Sep 2, 2024
9db2b69
genenums: auto generate "transformers"
adjabaev Sep 2, 2024
1697115
genenums: fix generics
adjabaev Sep 2, 2024
efebe81
genenums: add subfolders
adjabaev Sep 2, 2024
1735861
genenums: support default & remove usage of HashMap as it doesn't kee…
adjabaev Sep 2, 2024
a10e904
genenums: tweak file end line generation
adjabaev Sep 2, 2024
38b6576
genenums: try to fix rustfmt
adjabaev Sep 2, 2024
d7090fb
genenums: try to fix rustfmt
adjabaev Sep 2, 2024
798a82a
genenums: rustfmt stuff
adjabaev Sep 2, 2024
59a793f
genenums: add note for when intersperse is stabilised
adjabaev Sep 3, 2024
765ccd2
java: working on measure function stuff
adjabaev Sep 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,6 @@ members = [
"scripts/import-yoga-tests",
"benches",
"taffy_stylo",
"bindings/java",
"scripts/genenums"
]
6 changes: 6 additions & 0 deletions bindings/java/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.idea
*.iml
out
*.class
/target
/java/target
19 changes: 19 additions & 0 deletions bindings/java/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "jtaffy"
version = "0.0.1"
authors = [
"Arby Djabaev <contact@arby.be>"
]
edition = "2021"
include = ["src/**/*", "Cargo.toml"]
description = "Java bindings to Taffy (A flexible UI layout library)"
repository = "https://github.com/DioxusLabs/taffy"
license = "MIT"

[lib]
crate-type = ["cdylib"]
name = "jtaffy"

[dependencies]
jni = "0.21.1"
taffy = { path = "../.." }
40 changes: 40 additions & 0 deletions bindings/java/java/examples/java/com/dioxuslabs/taffy/Basic.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.dioxuslabs.taffy;

import com.dioxuslabs.taffy.enums.AlignContent;
import com.dioxuslabs.taffy.geom.Size;
import com.dioxuslabs.taffy.geom.measure.Dimension;
import com.dioxuslabs.taffy.style.Style;

import java.util.List;

/**
* Equivalent of taffy/examples/basic.rs
*/
public class Basic {
public static void main(String[] args) {
TaffyTree taffy = new TaffyTree();

long child = taffy.newLeaf(
Style.builder().size(new Size<>(Dimension.percent(0.5f), Dimension.auto()))
);

long node = taffy.newWithChildren(
Style.builder().size(Size.length(Dimension.class, 100, 100))
.justifyContent(AlignContent.CENTER),
List.of(child)
);

System.out.println("Compute layout with 100x100 viewport:");
taffy.computeLayout(
node,
Size.definiteAvailableSize(100, 100)
);
System.out.println("node: " + taffy.layout(node).toString());
System.out.println("child: " + taffy.layout(child).toString());

System.out.println("Compute layout with undefined (infinite) viewport:");
taffy.computeLayout(node, Size.maxContentAvailableSize());
System.out.println("node: " + taffy.layout(node).toString());
System.out.println("child: " + taffy.layout(child).toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.dioxuslabs.taffy;

import com.dioxuslabs.taffy.geom.Size;
import com.dioxuslabs.taffy.geom.measure.LengthPercentage;
import com.dioxuslabs.taffy.style.Style;

import java.util.List;

/**
* Equivalent of taffy/examples/flexbox_gap.rs
*/
public class FlexboxGap {
public static void main(String[] args) {
TaffyTree taffy = new TaffyTree();

Style childStyle = Style.builder()
.size(Size.lengthDimension(20, 20));
long child0 = taffy.newLeaf(childStyle);
long child1 = taffy.newLeaf(childStyle);
long child2 = taffy.newLeaf(childStyle);

long root = taffy.newWithChildren(
Style.builder()
.gap(new Size<>(LengthPercentage.length(10), LengthPercentage.zero())),
List.of(child0, child1, child2)
);

// Compute layout and print result
taffy.computeLayout(root, Size.maxContentAvailableSize());
taffy.printTree(root);
}
}
75 changes: 75 additions & 0 deletions bindings/java/java/examples/java/com/dioxuslabs/taffy/Measure.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.dioxuslabs.taffy;

import com.dioxuslabs.taffy.common.Image.ImageContext;
import com.dioxuslabs.taffy.common.Text;
import com.dioxuslabs.taffy.common.Text.FontMetrics;
import com.dioxuslabs.taffy.common.Text.TextContext;
import com.dioxuslabs.taffy.enums.Display;
import com.dioxuslabs.taffy.enums.FlexDirection;
import com.dioxuslabs.taffy.geom.Size;
import com.dioxuslabs.taffy.geom.measure.AvailableSpace;
import com.dioxuslabs.taffy.geom.measure.Dimension;
import com.dioxuslabs.taffy.style.Style;

import java.util.List;

import static com.dioxuslabs.taffy.common.Image.imageMeasureFunction;
import static com.dioxuslabs.taffy.common.Text.LOREM_IPSUM;
import static com.dioxuslabs.taffy.common.Text.textMeasureFunction;

/**
* Equivalent of taffy/examples/measure.rs
*/
public class Measure {
public static Size<Float> measureFunction(
Size<Float> knownDimensions,
Size<AvailableSpace> availableSpace,
Object nodeContext,
FontMetrics fontMetrics
) {
if (knownDimensions.bothAxisDefined()) {
return new Size<>(knownDimensions.width(), knownDimensions.height());
}

if (nodeContext instanceof TextContext nc) {
return textMeasureFunction(knownDimensions, availableSpace, nc, fontMetrics);
} else if (nodeContext instanceof ImageContext nc) {
return imageMeasureFunction(knownDimensions, nc);
} else {
return Size.zero(Float.class);
}
}

public static void main(String[] args) {
TaffyTree taffy = new TaffyTree();

FontMetrics fontMetrics = new FontMetrics(10f, 10f);

long textNode = taffy.newLeafWithContext(
Style.def(),
new TextContext(LOREM_IPSUM, Text.WritingMode.HORIZONTAL)
);

long imageNode = taffy.newLeafWithContext(
Style.def(),
new ImageContext(400f, 300f)
);

long root = taffy.newWithChildren(
Style.builder()
.display(Display.FLEX)
.flexDirection(FlexDirection.COLUMN)
.size(new Size<>(Dimension.length(200), Dimension.auto())),
List.of(textNode, imageNode)
);

// Compute layout and print result
taffy.computeLayoutWithMeasure(
root,
Size.maxContentAvailableSize()
// todo measure func
);

taffy.printTree(root);
}
}
53 changes: 53 additions & 0 deletions bindings/java/java/examples/java/com/dioxuslabs/taffy/Nested.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.dioxuslabs.taffy;

import com.dioxuslabs.taffy.geom.Size;
import com.dioxuslabs.taffy.geom.measure.Dimension;
import com.dioxuslabs.taffy.style.Style;

import java.util.List;

/**
* Equivalent of taffy/examples/nested.rs
*/
public class Nested {
public static void main(String[] args) {
TaffyTree taffy = new TaffyTree();

// left
long childT1 = taffy.newLeaf(
Style.builder().size(Size.lengthDimension(5, 5))
);

long div1 = taffy.newWithChildren(
Style.builder().size(new Size<>(Dimension.percent(0.5f), Dimension.percent(1f))),
List.of(childT1)
);

// right
long childT2 = taffy.newLeaf(
Style.builder().size(Size.lengthDimension(5, 5))
);

long div2 = taffy.newWithChildren(
Style.builder().size(new Size<>(Dimension.percent(0.5f), Dimension.percent(1f))),
List.of(childT2)
);

long container = taffy.newWithChildren(
Style.builder().size(Size.percent(Dimension.class, 1, 1)),
List.of(div1, div2)
);

taffy.computeLayout(
container,
Size.definiteAvailableSize(100, 100)
);
System.out.println("node: " + taffy.layout(container).toString());

System.out.println("div1: " + taffy.layout(div1).toString());
System.out.println("div2: " + taffy.layout(div2).toString());

System.out.println("child1: " + taffy.layout(childT1).toString());
System.out.println("child: " + taffy.layout(childT2).toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.dioxuslabs.taffy.common;

import com.dioxuslabs.taffy.geom.Size;

public class Image {
public record ImageContext(
float width,
float height
) {
}

public static Size<Float> imageMeasureFunction(Size<Float> knownDimensions, ImageContext imageContext) {
Float width = knownDimensions.width();
Float height = knownDimensions.height();

if (width != null && height != null) {
return new Size<>(width, height);
} else if (width != null) {
return new Size<>(width, (width / imageContext.width) * imageContext.height);
} else if (height != null) {
return new Size<>((height / imageContext.height) * imageContext.width, height);
} else {
return new Size<>(imageContext.width, imageContext.height);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.dioxuslabs.taffy.common;

import com.dioxuslabs.taffy.enums.AbsoluteAxis;
import com.dioxuslabs.taffy.geom.Size;
import com.dioxuslabs.taffy.geom.measure.AvailableSpace;

import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;

public class Text {
public static String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

public record FontMetrics(
float charWidth,
float charHeight
) {
}

public enum WritingMode {
HORIZONTAL,
VERTICAL
}

public record TextContext(
String textContent,
WritingMode writingMode
) {
}

public static Size<Float> textMeasureFunction(
Size<Float> knownDimensions,
Size<AvailableSpace> availableSpace,
TextContext textContext,
FontMetrics fontMetrics
) {
AbsoluteAxis inlineAxis = textContext.writingMode == WritingMode.HORIZONTAL ? AbsoluteAxis.HORIZONTAL : AbsoluteAxis.VERTICAL;
AbsoluteAxis blockAxis = inlineAxis == AbsoluteAxis.HORIZONTAL ? AbsoluteAxis.VERTICAL : AbsoluteAxis.HORIZONTAL;

String[] words = textContext.textContent.split(" ");

if (words.length == 0) {
return Size.zero(Float.class);
}

int minLineLength = Arrays.stream(words).map(String::length).max(Integer::compareTo).orElse(0);
AtomicInteger maxLineLength = new AtomicInteger();
Arrays.stream(words).forEach(line -> maxLineLength.addAndGet(line.length()));

Float abs = knownDimensions.getAbs(inlineAxis);
float inlineSize;
if (abs == null) {
AvailableSpace as = availableSpace.getAbs(inlineAxis);
if (as.isMinContent()) {
inlineSize = minLineLength * fontMetrics.charWidth;
} else if (as.isMaxContent()) {
inlineSize = maxLineLength.get() * fontMetrics.charWidth;
} else {
inlineSize = Math.max(Math.min(as.val(), maxLineLength.get() * fontMetrics.charWidth), minLineLength * fontMetrics.charWidth);
}
} else {
inlineSize = abs;
}

abs = knownDimensions.getAbs(blockAxis);
float blockSize;
if (abs == null) {
int inlineLineLength = (int) Math.floor(inlineSize / fontMetrics.charWidth);
int lineCount = 1;
int currentLineLength = 0;

for (String word : words) {
if (currentLineLength == 0) {
// first word
currentLineLength = word.length();
} else if (currentLineLength + word.length() + 1 > inlineLineLength) {
// every word past the first needs to check for line length including the space between words
// note: a real implementation of this should handle whitespace characters other than ' '
// and do something more sophisticated for long words
lineCount += 1;
currentLineLength = word.length();
} else {
// add the word and a space
currentLineLength += word.length() + 1;
}
}

blockSize = lineCount * fontMetrics.charHeight;
} else {
blockSize = abs;
}

if (textContext.writingMode == WritingMode.HORIZONTAL) {
return new Size<>(inlineSize, blockSize);
} else {
return new Size<>(blockSize, inlineSize);
}
}
}
Loading
Loading