1use std::collections::{HashMap, HashSet, VecDeque};
2use std::fmt::Write;
3
4use cassowary;
5use cassowary::strength::*;
6use cassowary::{Variable, Constraint, Expression};
7use cassowary::WeightedRelation::*;
8
9use super::{LayoutId, Layout, VarType, LayoutVars, EditVariable, Rect, Point, Size};
10
11pub struct LimnSolver {
12 pub solver: cassowary::Solver,
13 pub strict: bool,
14 layouts: LayoutManager,
15}
16
17impl LimnSolver {
18 pub fn new() -> Self {
19 LimnSolver {
20 solver: cassowary::Solver::new(),
21 strict: false,
22 layouts: LayoutManager::new(),
23 }
24 }
25
26 pub fn update_layout(&mut self, layout: &mut Layout) {
27
28 let registered = self.layouts.layouts.contains_key(&layout.id);
29 if !registered {
30 self.layouts.register_layout(layout);
31 }
32 self.layouts.update_layout(layout);
33
34 for child in layout.get_removed_children() {
35 self.remove_layout(child);
36 }
37 for constraint in layout.get_removed_constraints() {
38 self.layouts.remove_constraint(&constraint);
39 self.remove_constraint(&constraint);
40 }
41 if !registered {
42 for constraint in self.layouts.dequeue_constraints(layout) {
43 self.add_constraint(constraint.clone());
44 }
45 }
46
47 if layout.hidden && !self.layouts.layout_hidden(layout.id) {
48 self.hide_layout(layout.id);
49 } else if !layout.hidden && self.layouts.layout_hidden(layout.id) {
50 self.unhide_layout(layout.id);
51 }
52 for constraint in layout.get_constraints() {
53 if self.layouts.add_constraint(&constraint) {
54 self.add_constraint(constraint.clone());
55 }
56 }
57 for edit_var in layout.get_edit_vars() {
58 self.update_edit_var(&edit_var);
59 self.layouts.update_edit_var(layout.id, edit_var);
60 }
61 }
62 fn update_edit_var(&mut self, edit_var: &EditVariable) {
63 let &EditVariable { var, val, strength } = edit_var;
64 if !self.solver.has_edit_variable(&var) {
65 debug!("add edit_var {}", self.layouts.fmt_variable(var));
66 self.solver.add_edit_variable(var, strength).unwrap();
67 }
68 if val.is_finite() {
69 self.solver.suggest_value(var, val).unwrap();
70 debug!("suggest edit_var {} {}", self.layouts.fmt_variable(var), val);
71 } else {
72 debug!("invalid edit_var {} {}", self.layouts.fmt_variable(var), val);
73 }
74 }
75 fn add_constraint(&mut self, constraint: Constraint) {
76 debug!("adding constraint {}", self.layouts.fmt_constraint(&constraint));
77 if self.solver.add_constraint(constraint.clone()).is_err() {
78 eprintln!("Failed to add constraint {}", self.layouts.fmt_constraint(&constraint));
79 self.debug_associated_constraints(&constraint);
80 if self.strict {
81 panic!("Solver unsatisfiable");
82 }
83 }
84 }
85
86 fn remove_constraint(&mut self, constraint: &Constraint) {
87 debug!("removing constraint {}", self.layouts.fmt_constraint(constraint));
88 if self.solver.has_constraint(constraint) {
89 self.solver.remove_constraint(constraint).unwrap();
90 }
91 }
92
93 pub fn remove_layout(&mut self, id: LayoutId) {
94 if let Some(layout) = self.layouts.layouts.remove(&id) {
95 for constraint in layout.constraints {
96 self.remove_constraint(&constraint);
97 }
98 for var in layout.vars.array().iter() {
99 self.layouts.var_ids.remove(&var);
100 }
101 }
102 }
103
104 pub fn hide_layout(&mut self, id: LayoutId) {
105 if !self.layouts.layout_hidden(id) {
106 for constraint in self.layouts.layouts[&id].constraints.clone() {
107 self.remove_constraint(&constraint);
108 }
109 {
110 let layout = self.layouts.layouts.get_mut(&id).unwrap();
111 if layout.hidden_constraints.len() == 0 {
112 layout.hidden_constraints.extend(vec![
113 layout.vars.width | EQ(REQUIRED) | 0.0, layout.vars.height | EQ(REQUIRED) | 0.0,
114 layout.vars.left | EQ(REQUIRED) | 0.0, layout.vars.top | EQ(REQUIRED) | 0.0,
115 layout.vars.right | EQ(REQUIRED) | 0.0, layout.vars.bottom | EQ(REQUIRED) | 0.0,
116 ]);
117 }
118 layout.hidden = true;
119 }
120 for constraint in self.layouts.layouts[&id].hidden_constraints.clone() {
121 self.add_constraint(constraint.clone());
122 }
123 }
124 let children = self.layouts.layouts[&id].children.clone();
125 for child in children {
126 self.hide_layout(child);
127 }
128 }
129 pub fn unhide_layout(&mut self, id: LayoutId) {
130 if self.layouts.layout_hidden(id) {
131 for constraint in self.layouts.layouts[&id].hidden_constraints.clone() {
132 self.remove_constraint(&constraint);
133 }
134 for constraint in self.layouts.layouts[&id].constraints.clone() {
135 if !self.solver.has_constraint(&constraint) {
136 let mut hidden = false;
137 for layout_id in self.layouts.dependent_layouts(&constraint) {
138 if layout_id != id && self.layouts.layout_hidden(layout_id) {
139 hidden = true;
140 break;
141 }
142 }
143 if !hidden {
144 self.add_constraint(constraint.clone());
145 }
146 }
147 }
148 let layout = self.layouts.layouts.get_mut(&id).unwrap();
149 layout.hidden = false;
150 }
151 let children = self.layouts.layouts[&id].children.clone();
152 for child in children {
153 self.unhide_layout(child);
154 }
155 }
156 pub fn update_solver<F>(&mut self, f: F)
157 where F: Fn(&mut cassowary::Solver)
158 {
159 f(&mut self.solver);
160 }
161
162 pub fn has_edit_variable(&mut self, v: &Variable) -> bool {
163 self.solver.has_edit_variable(v)
164 }
165 pub fn has_constraint(&self, constraint: &Constraint) -> bool {
166 self.solver.has_constraint(constraint)
167 }
168
169 pub fn fetch_changes(&mut self) -> Vec<(LayoutId, VarType, f64)> {
170 let mut changes = Vec::new();
171 for &(var, val) in self.solver.fetch_changes() {
172 debug!("solver {} = {}", self.layouts.fmt_variable(var), val);
173 if let Some(layout_id) = self.layouts.var_ids.get(&var) {
174 let var_type = self.layouts.layouts[&layout_id].vars.var_type(var);
175 changes.push((*layout_id, var_type, val));
176 }
177 }
178 changes
179 }
180
181 pub fn debug_variables(&self) {
182 println!("VARIABLES");
183 for var in self.layouts.var_ids.keys() {
184 println!("{}", self.layouts.fmt_variable(*var));
185 }
186 }
187
188 pub fn debug_constraints(&self) {
189 println!("CONSTRAINTS");
190 let mut shown_constraints = HashSet::new();
191 let mut layouts = VecDeque::new();
192 layouts.push_front(self.layouts.root);
193 while let Some(layout) = layouts.pop_front() {
194 println!("{}", self.layouts.layout_name(layout).to_uppercase());
195 for constraint in &self.layouts.layouts[&layout].constraints {
196 if !shown_constraints.contains(constraint) && self.solver.has_constraint(constraint) {
197 self.debug_constraint(constraint);
198 shown_constraints.insert(constraint.clone());
199 }
200 }
201 println!("EDIT_VARS");
202 for (_, edit_var) in &self.layouts.layouts[&layout].edit_vars {
203 println!("{}", self.layouts.fmt_edit_variable(edit_var));
204 }
205 layouts.extend(self.layouts.children(layout));
206 }
207 }
208
209 pub fn debug_constraint(&self, constraint: &Constraint) {
210 println!("{}", self.layouts.fmt_constraint(constraint));
211 }
212
213 pub fn debug_associated_constraints(&self, constraint: &Constraint) {
214 let mut visited_constraints = HashSet::new();
215 let mut new_constraints = HashSet::new();
216 new_constraints.insert(constraint.clone());
217
218 loop {
219 if new_constraints.len() == 0 {
220 break;
221 }
222 let mut newer_constraints = HashSet::new();
223 for constraint in new_constraints.drain() {
224 for var in constraint_vars(&constraint) {
225 for constraint in self.layouts.constraints_for(var) {
226 if constraint.strength() >= REQUIRED &&
227 !visited_constraints.contains(constraint) &&
228 self.solver.has_constraint(&constraint) {
229 newer_constraints.insert(constraint.clone());
230 }
231 }
232 }
233 visited_constraints.insert(constraint);
234 }
235 new_constraints = newer_constraints;
236 }
237 for constraint in visited_constraints {
238 self.debug_constraint(&constraint);
239 }
240 }
241
242 pub fn debug_layouts(&self) {
243 println!("LAYOUTS");
244 let mut layouts = VecDeque::new();
245 layouts.push_front(self.layouts.root);
246 while let Some(layout) = layouts.pop_front() {
247 self.debug_layout(layout);
248 layouts.extend(self.layouts.children(layout));
249 }
250 }
251
252 pub fn debug_layout(&self, id: LayoutId) {
253 let bounds = {
254 let get_val = |var| self.solver.get_value(var) as f32;
255 let vars = &self.layouts.layouts[&id].vars;
256 let origin = Point::new(get_val(vars.left), get_val(vars.top));
257 let size = Size::new(get_val(vars.width), get_val(vars.height));
258 Rect::new(origin, size)
259 };
260 println!("{} {}", self.layouts.layout_name(id), bounds);
261 }
262}
263
264fn constraint_vars(constraint: &Constraint) -> Vec<Variable> {
265 constraint.expr().terms.iter().map(|term| term.variable).collect()
266}
267
268struct LayoutInternal {
269 vars: LayoutVars,
270 name: Option<String>,
271 associated_vars: HashMap<Variable, String>,
272 edit_vars: HashMap<Variable, EditVariable>,
273 constraints: HashSet<Constraint>,
274 children: Vec<LayoutId>,
275 hidden: bool,
276 hidden_constraints: Vec<Constraint>,
277}
278pub struct LayoutManager {
279 root: LayoutId,
280 var_ids: HashMap<Variable, LayoutId>,
281 layouts: HashMap<LayoutId, LayoutInternal>,
282 constraints: HashMap<Variable, HashSet<Constraint>>,
283
284 pending_constraints: HashMap<Variable, Vec<Constraint>>,
285 missing_vars: HashMap<Constraint, usize>,
286}
287
288impl LayoutManager {
289
290 pub fn new() -> Self {
291 LayoutManager {
292 root: 0,
293 var_ids: HashMap::new(),
294 layouts: HashMap::new(),
295 constraints: HashMap::new(),
296 pending_constraints: HashMap::new(),
297 missing_vars: HashMap::new(),
298 }
299 }
300
301 pub fn register_layout(&mut self, layout: &mut Layout) {
302 let id = layout.id;
303
304 for var in layout.vars.array().iter() {
305 self.var_ids.insert(*var, id);
306 }
307 let layout = LayoutInternal {
308 vars: layout.vars.clone(),
309 name: layout.name.clone(),
310 associated_vars: HashMap::new(),
311 edit_vars: HashMap::new(),
312 constraints: HashSet::new(),
313 children: layout.children.clone(),
314 hidden: false,
315 hidden_constraints: Vec::new(),
316 };
317 self.layouts.insert(id, layout);
318 }
319
320 pub fn update_layout(&mut self, layout: &mut Layout) {
321 let internal_layout = self.layouts.get_mut(&layout.id).unwrap();
322 for (var, name) in layout.get_associated_vars() {
323 self.var_ids.insert(var, layout.id);
324 internal_layout.associated_vars.insert(var, name);
325 }
326 internal_layout.name = layout.name.clone();
327 }
328
329 pub fn add_constraint(&mut self, constraint: &Constraint) -> bool {
330 let mut missing_layouts = false;
331 for term in &constraint.expr().terms {
332 self.constraints.entry(term.variable).or_insert_with(HashSet::new).insert(constraint.clone());
333 if self.var_ids.contains_key(&term.variable) {
334 let layout_id = self.var_ids[&term.variable];
335 self.layouts.get_mut(&layout_id).unwrap().constraints.insert(constraint.clone());
336 } else {
337 missing_layouts = true;
338 self.queue_constraint(term.variable, constraint.clone());
339 }
340 }
341 !missing_layouts
342 }
343
344 pub fn remove_constraint(&mut self, constraint: &Constraint) {
345 for term in &constraint.expr().terms {
346 self.constraints.entry(term.variable).or_insert_with(HashSet::new).remove(constraint);
347 if self.var_ids.contains_key(&term.variable) {
348 let layout_id = self.var_ids[&term.variable];
349 self.layouts.get_mut(&layout_id).unwrap().constraints.remove(constraint);
350 }
351 }
352 }
353 fn update_edit_var(&mut self, layout_id: LayoutId, edit_var: EditVariable) {
354 self.layouts.get_mut(&layout_id).unwrap().edit_vars.insert(edit_var.var, edit_var);
355 }
356
357 fn constraints_for(&self, variable: Variable) -> &HashSet<Constraint> {
358 &self.constraints[&variable]
359 }
360
361 pub fn queue_constraint(&mut self, variable: Variable, constraint: Constraint) {
364 *self.missing_vars.entry(constraint.clone()).or_insert(0) += 1;
365 self.pending_constraints.entry(variable).or_insert_with(Vec::new)
366 .push(constraint);
367 }
368 pub fn dequeue_constraints(&mut self, layout: &mut Layout) -> Vec<Constraint> {
371 let constraints = {
372 let mut constraints = Vec::new();
373 for var in self.layout_vars(layout.id) {
374 if let Some(pending) = self.pending_constraints.remove(&var) {
375 for constraint in pending {
376 *self.missing_vars.get_mut(&constraint).unwrap() -= 1;
377 if self.missing_vars[&constraint] == 0 {
378 self.missing_vars.remove(&constraint);
379 constraints.push(constraint);
380 }
381 }
382 }
383 }
384 constraints
385 };
386 for constraint in &constraints {
387 for term in &constraint.expr().terms {
388 let layout_id = self.var_ids[&term.variable];
389 self.layouts.get_mut(&layout_id).unwrap().constraints.insert(constraint.clone());
390 }
391 }
392 constraints
393 }
394
395 pub fn layout_hidden(&self, id: LayoutId) -> bool {
396 self.layouts[&id].hidden
397 }
398
399 pub fn layout_name(&self, id: LayoutId) -> String {
400 self.layouts[&id].name.clone().unwrap_or("unknown".to_owned())
401 }
402
403 fn dependent_layouts(&self, constraint: &Constraint) -> Vec<LayoutId> {
404 constraint.expr().terms.iter().map(|term| self.var_ids[&term.variable]).collect()
405 }
406
407 pub fn children(&self, id: LayoutId) -> Vec<LayoutId> {
408 self.layouts[&id].children.clone()
409 }
410 pub fn layout_vars(&self, id: LayoutId) -> Vec<Variable> {
411 let layout = &self.layouts[&id];
412 layout.vars.array().iter().chain(layout.associated_vars.keys()).map(|var| *var).collect()
413 }
414
415 pub fn fmt_variable(&self, var: Variable) -> String {
416 let id = self.var_ids[&var];
417 let layout = &self.layouts[&id];
418 let layout_name = layout.name.clone().unwrap_or("unknown".to_owned());
419 let var_type = layout.vars.var_type(var);
420 let var_type = if let VarType::Other = var_type {
421 layout.associated_vars[&var].to_owned()
422 } else {
423 format!("{:?}", var_type).to_lowercase()
424 };
425 format!("{}.{}", layout_name, var_type)
426 }
427
428 pub fn fmt_edit_variable(&self, edit_var: &EditVariable) -> String {
429 format!("{} {} == {}", strength_desc(edit_var.strength), self.fmt_variable(edit_var.var), edit_var.val)
430 }
431
432 pub fn fmt_constraint(&self, constraint: &Constraint) -> String {
433 format!("{} {}", strength_desc(constraint.strength()), self.fmt_expression(&constraint.expr(), constraint.op()))
434 }
435
436 fn fmt_expression(&self, expression: &Expression, op: cassowary::RelationalOperator) -> String {
437 let (mut neg_terms, mut pos_terms) = (Vec::new(), Vec::new());
438 for term in expression.terms.iter() {
439 let neg = term.coefficient < 0.0;
440 let coef = term.coefficient.abs();
441 let coef = if coef == 1.0 { "".to_owned() } else { coef.to_string() };
442 let desc = format!("{}{}", coef, self.fmt_variable(term.variable));
443 if neg { neg_terms.push(desc) } else { pos_terms.push(desc) }
444 }
445 if expression.constant != 0.0 {
446 let neg = expression.constant < 0.0;
447 let desc = expression.constant.abs().to_string();
448 if neg { neg_terms.push(desc) } else { pos_terms.push(desc) }
449 }
450 let mut out = String::new();
451 if pos_terms.len() == 0 {
452 write!(out, "0").unwrap();
453 } else {
454 let mut terms = pos_terms.iter();
455 let term = terms.next().unwrap();
456 write!(out, "{}", term).unwrap();
457 for term in terms {
458 write!(out, " + {}", term).unwrap();
459 }
460 }
461 write!(out, " {} ", op).unwrap();
462 if neg_terms.len() == 0 {
463 write!(out, "0").unwrap();
464 } else {
465 let mut terms = neg_terms.iter();
466 let term = terms.next().unwrap();
467 write!(out, "{}", term).unwrap();
468 for term in terms {
469 write!(out, " + {}", term).unwrap();
470 }
471 }
472 out
473 }
474}
475
476fn strength_desc(strength: f64) -> &'static str {
478 if strength < WEAK { "WEAK-" }
479 else if strength == WEAK { "WEAK " }
480 else if strength < MEDIUM { "WEAK+" }
481 else if strength == MEDIUM { "MED " }
482 else if strength < STRONG { "MED+ " }
483 else if strength == STRONG { "STR " }
484 else if strength < REQUIRED { "STR+ " }
485 else if strength == REQUIRED { "REQD " }
486 else { "REQD+" }
487}