Cassowary solver
amolenaar opened this issue · 2 comments
Is your feature request related to a problem?
Gaphor is using its own constraint solver. The solver is quite simple and raises JuggleError
if not all constraints can be solved.
Describe the solution you'd like
Instead of using our own, we could leverage the work of others. I'm thinking about a Cassowary solver.
Esp. the syntax of the Cassowary project is close to what we already do. It would be nice, though if we can register a callback when a variable has changed after the constraint system has stabilized.
Describe alternatives you've considered
I'm not aware of any other constraint solver that can be used to resolve UI constraints. Suggestions are welcome :).
Other information
If we combine this with something like CCSS (Constraint CSS, we'd probably define a function for this) we should be able to get auto-layouting for free.
Comparison of Gaphas' solver, Cassowary and Kiwisolver:
| | Gaphas | Cassowary | Kiwisolver |
| create solver | Solver() | SimplexSolver() | Solver() |
| create variable | Variable(42) | Variable('x1', 42) | Variable('x1') |
| create constraint | EqualConstraint(a, b) | a == b | a == b |
| add constraint | solver.add_constraint(cn) | solver.add_constraint(cn, strength=REQUIRED, weight=1.0) | solver.addConstraint(cn) |
| remove constraint | solver.remove_constraint(cn) | solver.remove_constraint(cn) | solver.removeConstraint(cn) |
| remove by var | - | - | - |
| variable strength | Variable(52, strength=REQUIRED) | solver.add_stay(middle, strength=REQUIRED, weight=1.0) | solver.addEditVariable(var, "strong") |
| constraint strength | - | solver.add_constraint(cn, strength=STRONG, weight=10) | solver.addConstraint((x1 == 40) | "weak") |
| allow edit variable | n.a. | solver.add_edit_var(var) | solver.addEditVariable(var, 42) |
| update value | var.value = 42 | solver.suggest_value(var, 42) | solver.suggestValue(var, 42) |
| get value | var.value | var.value | var.value() |
| solve | solver.solve() | solver.resolve() | solver.updateVariables() |
| projections | MatrixProjection(pos, matrix) | ?? | ?? |
Cassowary is pure Python, Kiwisolver is written in C++, with Python bindings.
To change to Cassowary/Kiwisolver means:
- We have to explicitly define which variables are subject to editing
- I do not know why this has to be defined explicitly
- How to we know a variable has changed -> This may cause a redraw.
- The Kiwisolver implementation is closer to what we have now (variables with strength)
- If we can use projections in a way we used to remains to be seen
I did some tests with Cassowary and it looks hard to implement positional projections (projecting positions in item-space to canvas-space and visa versa). It can be done by removing+adding constraints on every matrix change.
Alternatively: if we would just able to get rid of the JuggleError
(and produce sort of a consistent result) then we have no strict need for Cassowary/Simplex solver.