1#![cfg_attr(all(not(test), feature="clippy"), warn(result_unwrap_used))]
4#![cfg_attr(feature="clippy", warn(unseparated_literal_suffix))]
5#![cfg_attr(feature="clippy", warn(wrong_pub_self_convention))]
6
7#![cfg_attr(feature="clippy", feature(plugin))]
9#![cfg_attr(feature="clippy", plugin(clippy))]
10
11#![warn(missing_copy_implementations,
12 trivial_numeric_casts,
13 trivial_casts,
14 unused_extern_crates,
15 unused_import_braces,
16 unused_qualifications)]
17#![cfg_attr(feature="clippy", warn(cast_possible_truncation))]
18#![cfg_attr(feature="clippy", warn(cast_possible_wrap))]
19#![cfg_attr(feature="clippy", warn(cast_precision_loss))]
20#![cfg_attr(feature="clippy", warn(cast_sign_loss))]
21#![cfg_attr(feature="clippy", warn(missing_docs_in_private_items))]
22#![cfg_attr(feature="clippy", warn(mut_mut))]
23
24#![cfg_attr(feature="clippy", warn(print_stdout))]
27
28#![cfg_attr(all(not(test), feature="clippy"), warn(result_unwrap_used))]
32#![cfg_attr(feature="clippy", warn(unseparated_literal_suffix))]
33#![cfg_attr(feature="clippy", warn(wrong_pub_self_convention))]
34
35#[macro_use]
38extern crate log;
39#[macro_use]
40extern crate lazy_static;
41extern crate cassowary;
42extern crate euclid;
43
44use std::collections::HashSet;
45use std::ops::Drop;
46use std::mem;
47use std::rc::Rc;
48use std::cell::RefCell;
49
50use cassowary::{Variable, Constraint};
51use cassowary::WeightedRelation::*;
52use cassowary::strength::*;
53
54use euclid::{Point2D, Size2D, UnknownUnit};
55
56use self::constraint::ConstraintBuilder;
57use self::constraint::*;
58
59pub type Length = euclid::Length<f32, UnknownUnit>;
60pub type Size = Size2D<f32>;
61pub type Point = Point2D<f32>;
62pub type Rect = euclid::Rect<f32>;
63
64pub type LayoutId = usize;
65
66#[derive(Debug, Copy, Clone)]
69pub struct LayoutVars {
70 pub left: Variable,
71 pub top: Variable,
72 pub right: Variable,
73 pub bottom: Variable,
74 pub width: Variable,
75 pub height: Variable,
76}
77
78impl LayoutVars {
79 pub fn new() -> Self {
80 LayoutVars {
81 left: Variable::new(),
82 top: Variable::new(),
83 right: Variable::new(),
84 bottom: Variable::new(),
85 width: Variable::new(),
86 height: Variable::new(),
87 }
88 }
89
90 pub fn array(&self) -> [Variable; 6] {
92 [self.left,
93 self.top,
94 self.right,
95 self.bottom,
96 self.width,
97 self.height]
98 }
99
100 pub fn var_type(&self, var: Variable) -> VarType {
102 if var == self.left { VarType::Left }
103 else if var == self.top { VarType::Top }
104 else if var == self.right { VarType::Right }
105 else if var == self.bottom { VarType::Bottom }
106 else if var == self.width { VarType::Width }
107 else if var == self.height { VarType::Height }
108 else { VarType::Other }
109 }
110}
111
112#[derive(Debug, Clone, Copy)]
113pub enum VarType {
114 Left,
115 Top,
116 Right,
117 Bottom,
118 Width,
119 Height,
120 Other,
121}
122
123pub trait LayoutRef {
124 fn layout_ref(&self) -> LayoutVars;
125}
126
127impl<'a> LayoutRef for &'a mut Layout {
128 fn layout_ref(&self) -> LayoutVars {
129 self.vars
130 }
131}
132
133impl LayoutRef for Layout {
134 fn layout_ref(&self) -> LayoutVars {
135 self.vars
136 }
137}
138
139impl LayoutRef for LayoutVars {
140 fn layout_ref(&self) -> LayoutVars {
142 *self
143 }
144}
145
146pub struct Layout {
151 pub vars: LayoutVars,
152 pub name: Option<String>,
153 pub id: LayoutId,
154 container: Option<Rc<RefCell<LayoutContainer>>>,
155 parent: Option<LayoutId>,
156 children: Vec<LayoutId>,
157 edit_vars: Vec<EditVariable>,
158 constraints: HashSet<Constraint>,
159 new_constraints: HashSet<Constraint>,
160 removed_constraints: Vec<Constraint>,
161 removed_children: Vec<LayoutId>,
162 associated_vars: Vec<(Variable, String)>,
163 pub hidden: bool,
164}
165
166impl Layout {
167
168 pub fn new(id: LayoutId, name: Option<String>) -> Self {
170 let vars = LayoutVars::new();
171 let mut new_constraints = HashSet::new();
172 new_constraints.insert(vars.right - vars.left| EQ(REQUIRED) | vars.width);
173 new_constraints.insert(vars.bottom - vars.top | EQ(REQUIRED) | vars.height);
174 new_constraints.insert(vars.width | GE(REQUIRED) | 0.0);
175 new_constraints.insert(vars.height | GE(REQUIRED) | 0.0);
176 Layout {
177 vars: vars,
178 name: name,
179 id: id,
180 container: Some(Rc::new(RefCell::new(Frame::default()))),
181 parent: None,
182 children: Vec::new(),
183 edit_vars: Vec::new(),
184 constraints: HashSet::new(),
185 new_constraints: new_constraints,
186 removed_constraints: Vec::new(),
187 removed_children: Vec::new(),
188 associated_vars: Vec::new(),
189 hidden: false,
190 }
191 }
192
193 pub fn layout(&mut self) -> &mut Self {
194 self
195 }
196
197 pub fn no_container(&mut self) {
199 self.container = None;
200 }
201
202 pub fn set_container<T>(&mut self, container: T) where T: LayoutContainer + 'static {
206 self.container = Some(Rc::new(RefCell::new(container)));
207 }
208 pub fn edit_left(&mut self) -> VariableEditable {
209 let var = self.vars.left;
210 VariableEditable::new(self, var)
211 }
212 pub fn edit_top(&mut self) -> VariableEditable {
213 let var = self.vars.top;
214 VariableEditable::new(self, var)
215 }
216 pub fn edit_right(&mut self) -> VariableEditable {
217 let var = self.vars.right;
218 VariableEditable::new(self, var)
219 }
220 pub fn edit_bottom(&mut self) -> VariableEditable {
221 let var = self.vars.bottom;
222 VariableEditable::new(self, var)
223 }
224 pub fn edit_width(&mut self) -> VariableEditable {
225 let var = self.vars.width;
226 VariableEditable::new(self, var)
227 }
228 pub fn edit_height(&mut self) -> VariableEditable {
229 let var = self.vars.height;
230 VariableEditable::new(self, var)
231 }
232 pub fn create_constraint<B: ConstraintBuilder>(&self, builder: B) -> Vec<Constraint> {
233 builder.build(&self.vars)
234 }
235 pub fn add<B: ConstraintBuilder>(&mut self, builder: B) {
236 let new_constraints = builder.build(&self.vars);
237 self.new_constraints.extend(new_constraints);
238 }
239 pub fn remove_constraint(&mut self, constraint: Constraint) {
240 if !self.new_constraints.remove(&constraint) {
241 self.removed_constraints.push(constraint);
242 }
243 }
244 pub fn remove_constraints(&mut self, constraints: Vec<Constraint>) {
245 for constraint in constraints {
246 if !self.new_constraints.remove(&constraint) {
247 self.removed_constraints.push(constraint);
248 }
249 }
250 }
251 pub fn has_constraint(&mut self, constraints: &Vec<Constraint>) -> bool {
252 for constraint in constraints {
253 if self.new_constraints.contains(constraint) || self.constraints.contains(constraint) {
254 return true
255 }
256 }
257 false
258 }
259 pub fn get_constraints(&mut self) -> HashSet<Constraint> {
260 let new_constraints = mem::replace(&mut self.new_constraints, HashSet::new());
261 for constraint in new_constraints.clone() {
262 self.constraints.insert(constraint);
263 }
264 new_constraints
265 }
266 pub fn get_removed_constraints(&mut self) -> Vec<Constraint> {
267 let removed_constraints = mem::replace(&mut self.removed_constraints, Vec::new());
268 for ref constraint in &removed_constraints {
269 self.constraints.remove(constraint);
270 }
271 removed_constraints
272 }
273 pub fn get_edit_vars(&mut self) -> Vec<EditVariable> {
274 mem::replace(&mut self.edit_vars, Vec::new())
275 }
276 pub fn add_child(&mut self, child: &mut Layout) {
277 child.parent = Some(self.id);
278 self.children.push(child.id);
279 if let Some(container) = self.container.clone() {
280 container.borrow_mut().add_child(self, child);
281 }
282 }
283 pub fn remove_child(&mut self, child: &mut Layout) {
284 if let Some(container) = self.container.clone() {
285 container.borrow_mut().remove_child(self, child);
286 }
287 if let Some(pos) = self.children.iter().position(|id| child.id == *id) {
288 self.children.remove(pos);
289 }
290 self.removed_children.push(child.id);
291 }
292 pub fn get_removed_children(&mut self) -> Vec<LayoutId> {
293 mem::replace(&mut self.removed_children, Vec::new())
294 }
295 pub fn get_children(&self) -> &Vec<LayoutId> {
296 &self.children
297 }
298 pub fn add_associated_vars(&mut self, vars: &LayoutVars, name: &str) {
299 for var in vars.array().iter() {
300 let var_type = format!("{:?}", vars.var_type(*var)).to_lowercase();
301 self.associated_vars.push((*var, format!("{}.{}", name, var_type)));
302 }
303 }
304 pub fn add_associated_var(&mut self, var: Variable, name: &str) {
305 self.associated_vars.push((var, name.to_owned()));
306 }
307 pub fn get_associated_vars(&mut self) -> Vec<(Variable, String)> {
308 mem::replace(&mut self.associated_vars, Vec::new())
309 }
310 pub fn hide(&mut self) {
311 self.hidden = true;
312 }
313 pub fn show(&mut self) {
314 self.hidden = false;
315 }
316}
317
318pub struct VariableEditable<'a> {
319 pub builder: &'a mut Layout,
320 pub var: Variable,
321 val: Option<f64>,
322 strength: f64,
323}
324
325impl<'a> VariableEditable<'a> {
326 pub fn new(builder: &'a mut Layout, var: Variable) -> Self {
327 VariableEditable {
328 builder: builder,
329 var: var,
330 val: None,
331 strength: STRONG,
332 }
333 }
334 pub fn strength(mut self, strength: f64) -> Self {
335 self.strength = strength;
336 self
337 }
338 pub fn set(mut self, val: f32) -> Self {
339 self.val = Some(val as f64);
340 self
341 }
342}
343
344impl<'a> Drop for VariableEditable<'a> {
345 fn drop(&mut self) {
346 let edit_var = EditVariable::new(&self);
347 self.builder.edit_vars.push(edit_var);
348 }
349}
350
351#[derive(Debug, Copy, Clone)]
352pub struct EditVariable {
353 var: Variable,
354 val: f64,
355 strength: f64,
356}
357
358impl EditVariable {
359 fn new(editable: &VariableEditable) -> Self {
360 EditVariable {
361 var: editable.var,
362 val: editable.val.unwrap_or(0.0),
363 strength: editable.strength,
364 }
365 }
366}
367
368#[macro_export]
373macro_rules! constraints {
374 ( $ ( $ x : expr ) , * ) => {
375 constraints!( $ ( $ x , ) * )
376 };
377 ( $ ( $ x : expr , ) * ) => {
378 {
379 let mut vec: Vec<Box<ConstraintBuilder>> = Vec::new();
380 $(
381 vec.push(Box::new($x));
382 )*
383 vec
384 }
385 };
386}
387
388pub trait LayoutContainer {
390 fn add_child(&mut self, parent: &mut Layout, child: &mut Layout);
391 fn remove_child(&mut self, _: &mut Layout, _: &mut Layout) {}
392}
393
394#[derive(Debug, Default, Copy, Clone)]
395pub struct Frame {
396 padding: f32,
397}
398
399impl LayoutContainer for Frame {
400
401 fn add_child(&mut self, parent: &mut Layout, child: &mut Layout) {
403 child.add(constraints![
404 bound_by(&parent).padding(self.padding),
405 match_layout(&parent).strength(WEAK),
406 ]);
407 }
408}
409
410#[derive(Debug, Copy, Clone)]
411pub struct ExactFrame;
412
413impl LayoutContainer for ExactFrame {
414 fn add_child(&mut self, parent: &mut Layout, child: &mut Layout) {
415 child.add(match_layout(&parent));
416 }
417}
418
419pub mod solver;
420pub mod constraint;
421pub mod linear_layout;
422pub mod grid_layout;
423
424pub use self::solver::LimnSolver;
425
426lazy_static! {
427 pub static ref LAYOUT: LayoutVars = LayoutVars::new();
428}