Skip to content

Commit

Permalink
Split experiment
Browse files Browse the repository at this point in the history
  • Loading branch information
jswong65 committed Nov 11, 2022
1 parent 5767f16 commit b23e396
Show file tree
Hide file tree
Showing 6 changed files with 328 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import androidx.constraintlayout.core.state.helpers.ChainReference;
import androidx.constraintlayout.core.state.helpers.FlowReference;
import androidx.constraintlayout.core.state.helpers.GuidelineReference;
import androidx.constraintlayout.core.state.helpers.SplitReference;
import androidx.constraintlayout.core.widgets.ConstraintWidget;
import androidx.constraintlayout.core.widgets.Flow;

Expand Down Expand Up @@ -538,6 +539,12 @@ public static void parseJSON(String content, State state,
(CLObject) element
);
break;
case "Split":
parseSplitType(state,
elementName,
layoutVariables,
(CLObject) element);
break;
}
} else {
parseWidget(state, layoutVariables,
Expand Down Expand Up @@ -854,6 +861,45 @@ private static void parseChainType(String orientation,
}
}

private static void parseSplitType(State state,
String name,
LayoutVariables layoutVariables,
CLObject element) throws CLParsingException {

SplitReference split = state.getSplit(name);

for (String param : element.names()) {
switch (param) {
case "contains":
CLArray list = element.getArrayOrNull(param);
if (list != null) {
for (int j = 0; j < list.size(); j++) {

String elementNameReference = list.get(j).content();
ConstraintReference elementReference =
state.constraints(elementNameReference);
if (PARSER_DEBUG) {
System.out.println(
"Add REFERENCE "
+ "($elementNameReference = $elementReference) "
+ "TO BARRIER "
);
}
split.add(elementReference);
}
}
break;
case "orientation":
int orientation = element.get(param).getInt();
split.setOrientation(orientation);
break;
default:
ConstraintReference reference = state.constraints(name);
applyAttribute(state, layoutVariables, reference, element, param);
}
}
}

/**
* It's used to parse the Flow type of Helper with the following format:
* flowID: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import androidx.constraintlayout.core.state.helpers.FlowReference;
import androidx.constraintlayout.core.state.helpers.GuidelineReference;
import androidx.constraintlayout.core.state.helpers.HorizontalChainReference;
import androidx.constraintlayout.core.state.helpers.SplitReference;
import androidx.constraintlayout.core.state.helpers.VerticalChainReference;
import androidx.constraintlayout.core.widgets.ConstraintWidget;
import androidx.constraintlayout.core.widgets.ConstraintWidgetContainer;
Expand Down Expand Up @@ -93,6 +94,7 @@ public enum Helper {
LAYER,
HORIZONTAL_FLOW,
VERTICAL_FLOW,
SPLIT,
FLOW
}

Expand Down Expand Up @@ -324,6 +326,10 @@ public HelperReference helper(Object key, State.Helper type) {
reference = new FlowReference(this, type);
}
break;
case SPLIT: {
reference = new SplitReference(this, type);
}
break;
default: {
reference = new HelperReference(this, type);
}
Expand Down Expand Up @@ -368,6 +374,15 @@ public BarrierReference barrier(Object key, Direction direction) {
return (BarrierReference) reference.getFacade();
}

public SplitReference getSplit(Object key) {
ConstraintReference reference = constraints(key);
if (reference.getFacade() == null || !(reference.getFacade() instanceof SplitReference)) {
SplitReference flowReference = new SplitReference(this, Helper.SPLIT);
reference.setFacade(flowReference);
}
return (SplitReference) reference.getFacade();
}

/**
* Gets a reference to a Flow object. Creating it if needed.
* @param key id of the reference
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package androidx.constraintlayout.core.state.helpers;

import androidx.constraintlayout.core.state.HelperReference;
import androidx.constraintlayout.core.state.State;
import androidx.constraintlayout.core.utils.Split;
import androidx.constraintlayout.core.widgets.ConstraintWidget;
import androidx.constraintlayout.core.widgets.Flow;
import androidx.constraintlayout.core.widgets.HelperWidget;

public class SplitReference extends HelperReference {

public SplitReference(State state, State.Helper type) {
super(state, type);
}

protected Split mSplit;

protected ConstraintWidget mLeft;

protected ConstraintWidget mRight;

protected int mOrientation;

public ConstraintWidget getLeft() {
return mLeft;
}

public void setLeft(ConstraintWidget mLeft) {
this.mLeft = mLeft;
}

public ConstraintWidget getRight() {
return mRight;
}

public void setRight(ConstraintWidget mRight) {
this.mRight = mRight;
}

@Override
public HelperWidget getHelperWidget() {
if (mSplit == null) {
mSplit = new Split();
}
return mSplit;
}

@Override
public void setHelperWidget(HelperWidget widget) {
if (widget instanceof Flow) {
mSplit = (Split) widget;
} else {
mSplit = null;
}
}

public int getOrientation() {
return mOrientation;
}

public void setOrientation(int orientation) {
mOrientation = orientation;

}

@Override
public void apply() {
if (mLeft != null) {
mSplit.setFirst(mLeft);
}

if (mRight != null) {
mSplit.setSecond(mRight);
}

mSplit.setOrientation(mOrientation);

// General attributes of a widget
applyBase();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package androidx.constraintlayout.core.utils;

import androidx.constraintlayout.core.LinearSystem;
import androidx.constraintlayout.core.widgets.ConstraintWidget;
import androidx.constraintlayout.core.widgets.ConstraintWidgetContainer;
import androidx.constraintlayout.core.widgets.VirtualLayout;

public class Split extends VirtualLayout {

ConstraintWidget splitBar;

ConstraintWidget first;
ConstraintWidget second;
ConstraintWidgetContainer mContainer;
int orientation;

public Split() {
splitBar = new ConstraintWidget();
first = new ConstraintWidget();
second = new ConstraintWidget();
}

This comment has been minimized.

Copy link
@jafu888

jafu888 Nov 11, 2022

Collaborator

You should only have to create splitBar not create first and second


public void setFirst(ConstraintWidget a) {
first = a;
}

public void setSecond(ConstraintWidget b) {
second = b;
}

public void setSplitBar(ConstraintWidget splitBar) {
this.splitBar = splitBar;
}

public ConstraintWidget getFirst() {
return first;
}

public ConstraintWidget getSecond() {
return second;
}

public ConstraintWidget getSplitBar() {
return splitBar;
}

public ConstraintWidgetContainer getContainer() {
return mContainer;
}

public void setContainer(ConstraintWidgetContainer container) {
mContainer = container;
}

public int getOrientation() {
return orientation;
}

public void setOrientation(int orientation) {
this.orientation = orientation;
}

@Override
public void measure(int widthMode, int widthSize, int heightMode, int heightSize) {
super.measure(widthMode, widthSize, heightMode, heightSize);
for (int i = 0; i < mWidgetsCount; i++) {
if (i == 0) {
setFirst(mWidgets[i]);
} else if (i == 1) {
setSecond(mWidgets[i]);
} else if (i == 2) {
setSplitBar(mWidgets[i]);
}
}
splitBar.stringId = String.valueOf(splitBar.hashCode());
first.stringId = String.valueOf(first.hashCode());
second.stringId = String.valueOf(second.hashCode());
mContainer = (ConstraintWidgetContainer) getParent();

This comment has been minimized.

Copy link
@jafu888

jafu888 Nov 11, 2022

Collaborator

You should not set id on the second and first they should come from the Kotlin code

mContainer.add(splitBar);
}

@Override
public void addToSolver(LinearSystem system, boolean optimize) {
this.mTop.connect(getParent().mTop, 0);
this.mLeft.connect(getParent().mLeft, 0);
this.mRight.connect(getParent().mRight, 0);
this.mBottom.connect(getParent().mBottom, 0);

splitBar.mTop.connect(mTop, 0);
splitBar.mBottom.connect(mBottom, 0);
splitBar.mLeft.connect(mLeft, 0);
splitBar.mRight.connect(mRight, 0);

if (orientation == 0) {
first.mLeft.connect(mLeft, 0);
first.mRight.connect(splitBar.mLeft, 0);
first.mTop.connect(mTop, 0);
first.mBottom.connect(mBottom, 0);

This comment has been minimized.

Copy link
@jafu888

jafu888 Nov 11, 2022

Collaborator

should be wrapped in "if (first != null) { ..... }
So that if you do not set the first it does not crash.

This comment has been minimized.

Copy link
@jafu888

jafu888 Nov 11, 2022

Collaborator

same for second

second.mLeft.connect(splitBar.mRight, 0);
second.mRight.connect(mRight, 0);
second.mTop.connect(mTop, 0);
second.mBottom.connect(mBottom, 0);
} else {
first.mLeft.connect(mLeft, 0);
first.mRight.connect(mRight, 0);
first.mTop.connect(mTop, 0);
first.mBottom.connect(splitBar.mTop, 0);

second.mLeft.connect(mLeft, 0);
second.mRight.connect(mRight, 0);
second.mTop.connect(splitBar.mBottom, 0);
second.mBottom.connect(mBottom, 0);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import static org.junit.Assert.assertEquals;

import androidx.constraintlayout.core.utils.Split;
import androidx.constraintlayout.core.widgets.ConstraintAnchor;
import androidx.constraintlayout.core.widgets.ConstraintWidget;
import androidx.constraintlayout.core.widgets.ConstraintWidgetContainer;
Expand Down Expand Up @@ -230,4 +231,40 @@ public void didMeasures() {
System.out.println("A: " + a);
System.out.println("B: " + b);
}
@Test
public void testSplit() {
ConstraintWidgetContainer root = new ConstraintWidgetContainer(50, 50);
Split split = new Split();
split.setDebugName("split");

split.setHorizontalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.MATCH_PARENT);
split.setVerticalDimensionBehaviour(ConstraintWidget.DimensionBehaviour.MATCH_PARENT);
split.connect(ConstraintAnchor.Type.LEFT, root, ConstraintAnchor.Type.LEFT);
split.connect(ConstraintAnchor.Type.RIGHT, root, ConstraintAnchor.Type.RIGHT);
split.connect(ConstraintAnchor.Type.TOP, root, ConstraintAnchor.Type.TOP);
split.connect(ConstraintAnchor.Type.BOTTOM, root, ConstraintAnchor.Type.BOTTOM);
split.setOrientation(1);
root.add(split);
split.setContainer(root);
root.setMeasurer(new BasicMeasure.Measurer() {
@Override
public void measure(ConstraintWidget widget, BasicMeasure.Measure measure) {
measure.measuredWidth = widget.getWidth();
measure.measuredHeight = widget.getHeight();
}

@Override
public void didMeasures() {

}
});
root.setMeasurer(sMeasurer);
root.measure(Optimizer.OPTIMIZATION_NONE,
0, 0, 0, 0, 0, 0, 0, 0);
//root.layout();
System.out.println("root: " + root);
System.out.println("flow: " + split);
System.out.println("A: " + split.getFirst());
System.out.println("B: " + split.getSecond());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,36 @@ fun FlowBasicDemo6() {
}
}

// test adding constraints to parent
@Preview(group = "split")
@Composable
fun SplitDemo1() {
ConstraintLayout(
ConstraintSet("""
{
split: {
height: 'parent',
width: 'parent',
type: 'Split',
orientation: 0,
contains: ['btn1', 'btn2'],
},
btn1: {
height: 'spread',
width: 'spread',
}
}
""".trimIndent()),
modifier = Modifier.fillMaxSize()) {
val numArray = arrayOf("btn1", "btn2")
for (num in numArray) {
Button(
modifier = Modifier.layoutId(num),
onClick = {},
) {
Text(text = num)
}
}
}
}

0 comments on commit b23e396

Please sign in to comment.