def align_rows_or_columns(self, container, padding, rows, column_or_row, aligned_axis, aligned_axis_size, layout_axis, layout_axis_size): """ Align rows or columns elements with a column or row to the alignment of the parent container """ constraints = [] l_index = container.variables.alignment.domain.index("left") c_index = container.variables.alignment.domain.index("center") is_left = cb.eq(container.variables.alignment.id, str(l_index)) is_center = cb.eq(container.variables.alignment.id, str(c_index)) for row in rows: for i in range(len(row) - 1): shape1 = row[i] shape2 = row[i + 1] aligned_axis_size_value = str(shape1.computed_width( )) if aligned_axis_size == "width" else str( shape1.computed_height()) aligned_axis_size_value2 = str(shape2.computed_width( )) if aligned_axis_size == "width" else str( shape2.computed_height()) left_top_aligned = cb.eq(shape1.variables[aligned_axis].id, shape2.variables[aligned_axis].id) right_bottom_aligned = cb.eq( cb.add(shape1.variables[aligned_axis].id, aligned_axis_size_value), cb.add(shape2.variables[aligned_axis].id, aligned_axis_size_value2)) center_aligned = cb.eq( cb.add(shape1.variables[aligned_axis].id, cb.div(aligned_axis_size_value, "2")), cb.add(shape2.variables[aligned_axis].id, cb.div(aligned_axis_size_value2, "2"))) constraints.append( cb.ite( is_left, left_top_aligned, cb.ite(is_center, center_aligned, right_bottom_aligned))) # Shape 2 is exactly to the right of shape 1 or to the bottom if in a column layout_axis_size_value = str(shape1.computed_width( )) if layout_axis_size == "width" else str( shape1.computed_height()) constraints.append( cb.eq( cb.add(shape1.variables[layout_axis].id, cb.add(layout_axis_size_value, padding)), shape2.variables[layout_axis].id)) if len(constraints): return cb.and_expr(constraints) return True
def row_column_layout(self, is_rows, is_columns, groups, container, spacing, id_str=""): """ Perform either row or column layout """ row_column_constraints = [] row_column_constraints.append( cb.ite( is_rows, self.align_rows_or_columns(container, spacing, groups, "row", "y", "height", "x", "width"), "true")) row_column_constraints.append( cb.ite( is_columns, self.align_rows_or_columns(container, spacing, groups, "column", "x", "width", "y", "height"), "true")) row_column_constraints.append( cb.ite( is_rows, self.align_left_or_top(groups, spacing, "row", "x", "y", "height"), "true")) row_column_constraints.append( cb.ite( is_columns, self.align_left_or_top(groups, spacing, "column", "y", "x", "width"), "true")) row_column_constraints.append( cb.ite( is_rows, self.set_container_size_main_axis(container, spacing, groups, "height"), "true")) row_column_constraints.append( cb.ite( is_columns, self.set_container_size_main_axis(container, spacing, groups, "width"), "true")) row_column_constraints.append( cb.ite( is_rows, self.set_container_size_cross_axis(container, spacing, groups, "width"), "true")) row_column_constraints.append( cb.ite( is_columns, self.set_container_size_cross_axis(container, spacing, groups, "height"), "true")) return row_column_constraints
def get_min_height_constraint(child_i, shortest_i, child_shapes): """ Get the height value of the smallest height element in a set of shapes (child_shapes) """ if child_i < len(child_shapes): shortest_child = child_shapes[shortest_i] shortest_child_height = str(shortest_child.computed_height()) next_child = child_shapes[child_i] next_child_height = str(next_child.computed_height()) return cb.ite(cb.lt(shortest_child_height, next_child_height), get_max_height_constraint(child_i+1, shortest_i, child_shapes), get_max_height_constraint(child_i+1, child_i, child_shapes)) else: child_shape_height = str(child_shapes[shortest_i].computed_height()) return child_shape_height
def get_max_height_constraint(child_i, tallest_i, child_shapes): """ Get the height value of the tallest element in a set of shapes (child_shapes) """ if child_i < len(child_shapes): tallest_child = child_shapes[tallest_i] tallest_child_height = str(tallest_child.computed_height()) next_child = child_shapes[child_i] next_child_height = str(next_child.computed_height()) return cb.ite(cb.gt(tallest_child_height, next_child_height), get_max_height_constraint(child_i+1, tallest_i, child_shapes), get_max_height_constraint(child_i+1, child_i, child_shapes)) else: child_shape_height = str(child_shapes[tallest_i].computed_height()) return child_shape_height
def get_max_width_constraint(child_i, widest_i, child_shapes): """ Get the width value of the widest element in a set of shapes (child_shapes) """ if child_i < len(child_shapes): widest_child = child_shapes[widest_i] widest_child_width = str(widest_child.computed_width()) next_child = child_shapes[child_i] next_child_width = str(next_child.computed_width()) return cb.ite(cb.gt(widest_child_width, next_child_width), get_max_width_constraint(child_i+1, widest_i, child_shapes), get_max_width_constraint(child_i+1, child_i, child_shapes)) else: child_shape_width = str(child_shapes[widest_i].computed_width()) return child_shape_width
def get_min_width_constraint(child_i, thinnest_i, child_shapes): """ Get the width value of the smallest width element in a set of shapes (child_shapes) """ if child_i < len(child_shapes): thinnest_child = child_shapes[thinnest_i] thinnest_child_width = str(thinnest_child.computed_width()) next_child = child_shapes[child_i] next_child_width = str(next_child.computed_width()) return cb.ite(cb.lt(thinnest_child_width, next_child_width), get_min_width_constraint(child_i+1, thinnest_i, child_shapes), get_max_width_constraint(child_i+1, child_i, child_shapes)) else: child_shape_width = str(child_shapes[thinnest_i].computed_width()) return child_shape_width
def get_tallest_column_constraint(self, column_i, tallest_i, columns, spacing): """ Constraint to compute the tallest column in a column arranged container, which will be used to set the height on the parent container """ tallest_column = columns[tallest_i] tallest_column_height = self.get_column_height(tallest_column, spacing) if column_i < len(columns): next_column = columns[column_i] next_column_height = self.get_column_height(next_column, spacing) return cb.ite( cb.gt(tallest_column_height, next_column_height), self.get_tallest_column_constraint(column_i + 1, tallest_i, columns, spacing), self.get_tallest_column_constraint(column_i + 1, column_i, columns, spacing)) else: return tallest_column_height
def get_widest_row_constraint(self, row_i, widest_i, rows, spacing): """ Constraint to compute the widest row in a row arranged container, which will be used to set the width on the parent container """ widest_row = rows[widest_i] widest_row_width = self.get_row_width(widest_row, spacing) if row_i < len(rows): next_row = rows[row_i] next_row_width = self.get_row_width(next_row, spacing) return cb.ite( cb.gt(widest_row_width, next_row_width), self.get_widest_row_constraint(row_i + 1, widest_i, rows, spacing), self.get_widest_row_constraint(row_i + 1, row_i, rows, spacing)) else: return widest_row_width
def balanced_row_column_arrangement(self, is_rows, is_columns, container, rows_index, columns_index, spacing): # Columns/Rows arrangement constraints # Only apply if there are > 2 children elements arrangement = container.variables.arrangement extra_in_first = container.variables.extra_in_first if len(container.children) > 2: num_children_even = len(container.children) % 2 == 0 if num_children_even: groups = self.split_children_into_groups(container, True) constraints = self.row_column_layout(is_rows, is_columns, groups, container, spacing) self.constraints += cb.assert_expr( cb.and_expr(constraints), "container_" + container.shape_id + "_rows_columns") else: print("Rows and columns!!") groups_one = self.split_children_into_groups(container, True) const1 = self.row_column_layout(is_rows, is_columns, groups_one, container, spacing, "1") groups_two = self.split_children_into_groups(container, False) const2 = self.row_column_layout(is_rows, is_columns, groups_two, container, spacing, "2") self.constraints += cb.assert_expr( cb.ite(extra_in_first.id, cb.and_expr(const1), cb.and_expr(const2)), "container_" + container.shape_id + "_rows_columns") else: # Prevent columnns and rows variables if there are 2 children or less self.constraints += cb.assert_expr( cb.neq(arrangement.id, str(rows_index)), "container_" + container.shape_id + "_arrangement_neq_rows") self.constraints += cb.assert_expr( cb.neq(arrangement.id, str(columns_index)), "container_" + container.shape_id + "_arrangement_neq_columns")