Skip to content

Commit

Permalink
for #410 simple test program for cassowary-ruby gem
Browse files Browse the repository at this point in the history
  • Loading branch information
Cecil committed Oct 16, 2018
1 parent d117ff1 commit 92316d3
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 246 deletions.
69 changes: 69 additions & 0 deletions Tests/layout/cs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Not shoes, just ruby
# From https://cassowary.readthedocs.io/en/latest/topics/examples.html#gui-layout
# converted from python to ruby
#
# gem install cassowary-ruby
require 'cassowary'
include Cassowary

class Button
attr_accessor :left, :width
def initialize(identifier)
@left = Variable.new(name: 'left' + identifier, value: 0)
@width = Variable.new(name: 'width' + identifier, value: 0)
end
end
solver = SimplexSolver.new()
b1 = Button.new('b1')
b2 = Button.new('b2')

# window horizontal bounds
left_limit = Variable.new(name: 'left')
right_limit = Variable.new(name: 'width')
left_limit.value = 0
right_limit.value = 0 # CJC: ruby needs a value.

# left_limit stay is fixed (Required), right can be resized
solver.add_stay(left_limit)
solver.add_stay(right_limit, Strength::WeakStrength)

# The two buttons are the same width
solver.add_constraint(b1.width.cn_equal b2.width)

# Button1 starts 50 from the left margin.
solver.add_constraint(b1.left.cn_equal left_limit + 50)

# Button2 ends 50 from the right margin (???)
solver.add_constraint((left_limit + right_limit).cn_equal b2.left + b2.width + 50)

# Button2 starts at least 100 from the end of Button1. This is the
# "elastic" constraint in the system that will absorb extra space
# in the layout.
solver.add_constraint(b2.left.cn_equal b1.left + b1.width + 100)

# Button1 has a minimum width of 87
solver.add_constraint(b1.width.cn_geq 87)

# Button1's preferred width is 87
solver.add_constraint(b1.width.cn_equal 87, Strength::StrongStrength)

# Button2's minimum width is 113
solver.add_constraint(b2.width.cn_geq 113)

# Button2's preferred width is 113
solver.add_constraint(b2.width.cn_equal 113, Strength::StrongStrength)

puts "b1: #{b1.inspect}"
puts "b2: #{b2.inspect}"
puts "rl.value #{right_limit.value}"

puts "RESIZING Window to 500"
right_limit.value = 500
# example fails - args are wrong for a constraint
#right_limit_stay = solver.add_constraint(right_limit, Strength::RequiredStrength)
right_limit_stay = solver.add_stay(right_limit, Strength::RequiredStrength)
puts "b1: #{b1.inspect}"
puts "b2: #{b2.inspect}"
puts "rl.value #{right_limit.value}"


39 changes: 0 additions & 39 deletions lib/cassowary/constraint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,6 @@ module Cassowary
# Constraints are the restrictions on linear programming; an equality or
# inequality between two expressions.
###########################################################################
=begin
class AbstractConstraint(object):
def __init__(self, strength, weight=1.0):
self.strength = strength
self.weight = weight
self.is_edit_constraint = False
self.is_inequality = False
self.is_stay_constraint = False
@property
def is_required(self):
return self.strength == REQUIRED
def __repr__(self):
return '%s:{%s}(%s)' % (repr_strength(self.strength), self.weight, self.expression)
=end
class AbstractConstraint
attr_accessor :strength, :weight, :s_edit_constraint, :is_inequality,
:is_stay_contraint
Expand Down Expand Up @@ -60,29 +44,6 @@ def initialize(variable, strength=STRONG, weight=1.0)
end
end

=begin
class EditConstraint(AbstractConstraint):
def __init__(self, variable, strength=STRONG, weight=1.0):
super(EditConstraint, self).__init__(strength, weight)
self.variable = variable
self.expression = Expression(variable, -1.0, variable.value)
self.is_edit_constraint = True
def __repr__(self):
return 'edit:%s' % super(EditConstraint, self).__repr__()
class StayConstraint(AbstractConstraint):
def __init__(self, variable, strength=STRONG, weight=1.0):
super(StayConstraint, self).__init__(strength, weight)
self.variable = variable
self.expression = Expression(variable, -1.0, variable.value)
self.is_stay_constraint=True
def __repr__(self):
return 'stay:%s' % super(StayConstraint, self).__repr__()
=end

class Constraint < AbstractConstraint
LEQ = -1
Expand Down
126 changes: 2 additions & 124 deletions lib/cassowary/simplex_solver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,41 +46,7 @@ def initialize()
@rows[self.objective] = Expression()
@edit_variable_stack = [0]
end
=begin
def __repr__(self):
parts = []
parts.append('stay_error_vars: %s' % self.stay_error_vars)
parts.append('edit_var_map: %s' % self.edit_var_map)
return super(SimplexSolver, self).__repr__() + '\n' + '\n'.join(parts)
def add_constraint(self, cn, strength=None, weight=None):
if strength or weight:
cn = cn.clone()
if strength:
cn.strength = strength
if weight:
cn.weight = weight
# print('add_constraint', cn)
expr, eplus, eminus, prev_edit_constant = self.new_expression(cn)
if not self.try_adding_directly(expr):
self.add_with_artificial_variable(expr)
self.needs_solving = True
if cn.is_edit_constraint:
i = len(self.edit_var_map)
self.edit_var_map[cn.variable] = EditInfo(cn, eplus, eminus, prev_edit_constant, i)

if self.auto_solve:
self.optimize(self.objective)
self.set_external_variables()
return cn
=end
def add_constraint(cn, strength=nil, weight=nil)
if strength || weight
cn = cn.clone
Expand All @@ -105,23 +71,7 @@ def add_constraint(cn, strength=nil, weight=nil)
self.set_external_variables()
end
end
=begin
def add_edit_var(self, v, strength=STRONG):
# print("add_edit_var", v, strength)
return self.add_constraint(EditConstraint(v, strength))

def remove_edit_var(self, v):
self.remove_constraint(self.edit_var_map[v].constraint)
def edit(self):
return SolverEditContext(self)
def resolve(self):
self.dual_optimize()
self.set_external_variables()
self.infeasible_rows.clear()
self.reset_stay_constants()
=end
def add_edit_var(v, strength=STRONG)
rreturn self.add_constraint(EditConstraint.new(v, strength))
end
Expand All @@ -141,12 +91,10 @@ def resolve()
self.reset_stay_constants()
end

=begin
#######################################################################
# Internals
#######################################################################
=begin
def new_expression(self, cn):
# print("* new_expression", cn)
# print("cn.is_inequality == ", cn.is_inequality)
Expand Down Expand Up @@ -221,24 +169,6 @@ def new_expression(self, cn):
expr.multiply(-1.0)
return expr, eplus, eminus, prev_edit_constant
=end

=begin
def begin_edit(self):
assert len(self.edit_var_map) > 0
self.infeasible_rows.clear()
self.reset_stay_constants()
self.edit_variable_stack.append(len(self.edit_var_map))
def end_edit(self):
assert len(self.edit_var_map) > 0
self.resolve()
self.edit_variable_stack.pop()
self.remove_edit_vars_to(self.edit_variable_stack[-1])
def remove_all_edit_vars(self):
self.remove_edit_vars_to(0)
=end

def begin_edit()
#assert len(self.edit_var_map) > 0
self.infeasible_rows.clear()
Expand All @@ -257,25 +187,7 @@ def remove_all_edit_vars()
self.remove_edit_vars_to(0)
end

=begin
def remove_edit_vars_to(self, n):
try:
removals = []
for v, cei in self.edit_var_map.items():
if cei.index >= n:
removals.append(v)
for v in removals:
self.remove_edit_var(v)

assert len(self.edit_var_map) == n
except ConstraintNotFound:
raise InternalError('Constraint not found during internal removal')
def add_stay(self, v, strength=WEAK, weight=1.0):
return self.add_constraint(StayConstraint(v, strength, weight))
=end
def remove_edit_vars_to(n)
begin

Expand All @@ -287,6 +199,7 @@ def remove_edit_vars_to(n)
def add_stay(v, strength=WEAK, weight=1.0)
return self.add_constraint(StayConstraint.new(v, strength, weight))
end

=begin
def remove_constraint(self, cn):
# print("removeConstraint", cn)
Expand Down Expand Up @@ -409,43 +322,8 @@ def remove_constraint(self, cn):
self.optimize(self.objective)
self.set_external_variables()
=end
=begin
def resolve_array(self, new_edit_constants):
for v, cei in self.edit_var_map.items():
self.suggest_value(v, new_edit_constants[cei.index])
self.resolve()
def suggest_value(self, v, x):
cei = self.edit_var_map.get(v)
if not cei:
raise InternalError("suggestValue for variable %s, but var is not an edit variable" % v)
# print(cei)
delta = x - cei.prev_edit_constant
cei.prev_edit_constant = x
self.delta_edit_constant(delta, cei.edit_plus, cei.edit_minus)
def solve(self):
if self.needs_solving:
self.optimize(self.objective)
self.set_external_variables()
def set_edited_value(self, v, n):
if v not in self.columns or v not in self.rows:
v.value = n
if not approx_equal(n, v.value):
self.add_edit_var(v)
self.begin_edit()

self.suggest_value(v, n)

self.end_edit()
def add_var(self, v):
if v not in self.columns or v not in self.rows:
self.add_stay(v)
=end
def resolve_array(new_edit_constants)
@edit_var_map.each_pair do |v, cei|
self.suggest_value(v, new_edit_constants[cei.index]) # TODO class/type of cei is?
Expand Down
Loading

0 comments on commit 92316d3

Please sign in to comment.