layout: Respect margins
This commit is contained in:
		
							
								
								
									
										17
									
								
								src/data.rs
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/data.rs
									
									
									
									
									
								
							@ -850,4 +850,21 @@ mod tests {
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_layout_margins() {
 | 
				
			||||||
 | 
					        let out = Layout::from_file(PathBuf::from("tests/layout_margins.yaml"))
 | 
				
			||||||
 | 
					            .unwrap()
 | 
				
			||||||
 | 
					            .build(PanicWarn).0
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            out.margins,
 | 
				
			||||||
 | 
					            layout::Margins {
 | 
				
			||||||
 | 
					                top: 1.0,
 | 
				
			||||||
 | 
					                bottom: 3.0,
 | 
				
			||||||
 | 
					                left: 2.0,
 | 
				
			||||||
 | 
					                right: 2.0,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										119
									
								
								src/layout.rs
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								src/layout.rs
									
									
									
									
									
								
							@ -99,7 +99,7 @@ pub mod c {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Scale + translate
 | 
					    /// Translate and then scale
 | 
				
			||||||
    #[repr(C)]
 | 
					    #[repr(C)]
 | 
				
			||||||
    pub struct Transformation {
 | 
					    pub struct Transformation {
 | 
				
			||||||
        pub origin_x: f64,
 | 
					        pub origin_x: f64,
 | 
				
			||||||
@ -108,6 +108,14 @@ pub mod c {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    impl Transformation {
 | 
					    impl Transformation {
 | 
				
			||||||
 | 
					        /// Applies the new transformation after this one
 | 
				
			||||||
 | 
					        pub fn chain(self, next: Transformation) -> Transformation {
 | 
				
			||||||
 | 
					            Transformation {
 | 
				
			||||||
 | 
					                origin_x: self.origin_x + self.scale * next.origin_x,
 | 
				
			||||||
 | 
					                origin_y: self.origin_y + self.scale * next.origin_y,
 | 
				
			||||||
 | 
					                scale: self.scale * next.scale,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        fn forward(&self, p: Point) -> Point {
 | 
					        fn forward(&self, p: Point) -> Point {
 | 
				
			||||||
            Point {
 | 
					            Point {
 | 
				
			||||||
                x: (p.x - self.origin_x) / self.scale,
 | 
					                x: (p.x - self.origin_x) / self.scale,
 | 
				
			||||||
@ -195,7 +203,8 @@ pub mod c {
 | 
				
			|||||||
        println!("{:?}", button);
 | 
					        println!("{:?}", button);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Positions the layout within the available space
 | 
					    /// Positions the layout contents within the available space.
 | 
				
			||||||
 | 
					    /// The origin of the transformation is the point inside the margins.
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
    pub extern "C"
 | 
					    pub extern "C"
 | 
				
			||||||
    fn squeek_layout_calculate_transformation(
 | 
					    fn squeek_layout_calculate_transformation(
 | 
				
			||||||
@ -204,15 +213,10 @@ pub mod c {
 | 
				
			|||||||
        allocation_height: f64,
 | 
					        allocation_height: f64,
 | 
				
			||||||
    ) -> Transformation {
 | 
					    ) -> Transformation {
 | 
				
			||||||
        let layout = unsafe { &*layout };
 | 
					        let layout = unsafe { &*layout };
 | 
				
			||||||
        let size = layout.calculate_size();
 | 
					        layout.calculate_transformation(Size {
 | 
				
			||||||
        let h_scale = allocation_width / size.width;
 | 
					            width: allocation_width,
 | 
				
			||||||
        let v_scale = allocation_height / size.height;
 | 
					            height: allocation_height,
 | 
				
			||||||
        let scale = if h_scale < v_scale { h_scale } else { v_scale };
 | 
					        })
 | 
				
			||||||
        Transformation {
 | 
					 | 
				
			||||||
            origin_x: (allocation_width - (scale * size.width)) / 2.0,
 | 
					 | 
				
			||||||
            origin_y: (allocation_height - (scale * size.height)) / 2.0,
 | 
					 | 
				
			||||||
            scale: scale,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    #[no_mangle]
 | 
					    #[no_mangle]
 | 
				
			||||||
@ -427,7 +431,7 @@ pub struct ButtonPlace<'a> {
 | 
				
			|||||||
    offset: c::Point,
 | 
					    offset: c::Point,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
pub struct Size {
 | 
					pub struct Size {
 | 
				
			||||||
    pub width: f64,
 | 
					    pub width: f64,
 | 
				
			||||||
    pub height: f64,
 | 
					    pub height: f64,
 | 
				
			||||||
@ -560,6 +564,7 @@ pub enum ArrangementKind {
 | 
				
			|||||||
    Wide = 1,
 | 
					    Wide = 1,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub struct Margins {
 | 
					pub struct Margins {
 | 
				
			||||||
    pub top: f64,
 | 
					    pub top: f64,
 | 
				
			||||||
    pub bottom: f64,
 | 
					    pub bottom: f64,
 | 
				
			||||||
@ -713,7 +718,8 @@ impl Layout {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn calculate_size(&self) -> Size {
 | 
					    /// Calculates size without margins
 | 
				
			||||||
 | 
					    fn calculate_inner_size(&self) -> Size {
 | 
				
			||||||
        Size {
 | 
					        Size {
 | 
				
			||||||
            height: find_max_double(
 | 
					            height: find_max_double(
 | 
				
			||||||
                self.views.iter(),
 | 
					                self.views.iter(),
 | 
				
			||||||
@ -725,6 +731,39 @@ impl Layout {
 | 
				
			|||||||
            ),
 | 
					            ),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Size including margins
 | 
				
			||||||
 | 
					    fn calculate_size(&self) -> Size {
 | 
				
			||||||
 | 
					        let inner_size = self.calculate_inner_size();
 | 
				
			||||||
 | 
					        Size {
 | 
				
			||||||
 | 
					            width: self.margins.left + inner_size.width + self.margins.right,
 | 
				
			||||||
 | 
					            height: (
 | 
				
			||||||
 | 
					                self.margins.top
 | 
				
			||||||
 | 
					                + inner_size.height
 | 
				
			||||||
 | 
					                + self.margins.bottom
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    pub fn calculate_transformation(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        available: Size,
 | 
				
			||||||
 | 
					    ) -> c::Transformation {
 | 
				
			||||||
 | 
					        let size = self.calculate_size();
 | 
				
			||||||
 | 
					        let h_scale = available.width / size.width;
 | 
				
			||||||
 | 
					        let v_scale = available.height / size.height;
 | 
				
			||||||
 | 
					        let scale = if h_scale < v_scale { h_scale } else { v_scale };
 | 
				
			||||||
 | 
					        let outside_margins = c::Transformation {
 | 
				
			||||||
 | 
					            origin_x: (available.width - (scale * size.width)) / 2.0,
 | 
				
			||||||
 | 
					            origin_y: (available.height - (scale * size.height)) / 2.0,
 | 
				
			||||||
 | 
					            scale: scale,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        outside_margins.chain(c::Transformation {
 | 
				
			||||||
 | 
					            origin_x: self.margins.left,
 | 
				
			||||||
 | 
					            origin_y: self.margins.top,
 | 
				
			||||||
 | 
					            scale: 1.0,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod procedures {
 | 
					mod procedures {
 | 
				
			||||||
@ -907,4 +946,58 @@ mod test {
 | 
				
			|||||||
                .is_none()
 | 
					                .is_none()
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn check_bottom_margin() {
 | 
				
			||||||
 | 
					        // just one button
 | 
				
			||||||
 | 
					        let view = View::new(vec![
 | 
				
			||||||
 | 
					            (
 | 
				
			||||||
 | 
					                0.0,
 | 
				
			||||||
 | 
					                Row {
 | 
				
			||||||
 | 
					                    angle: 0,
 | 
				
			||||||
 | 
					                    buttons: vec![(
 | 
				
			||||||
 | 
					                        0.0,
 | 
				
			||||||
 | 
					                        Box::new(Button {
 | 
				
			||||||
 | 
					                            size: Size { width: 1.0, height: 1.0 },
 | 
				
			||||||
 | 
					                            ..*make_button_with_state("foo".into(), make_state())
 | 
				
			||||||
 | 
					                        }),
 | 
				
			||||||
 | 
					                    )]
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        let layout = Layout {
 | 
				
			||||||
 | 
					            current_view: String::new(),
 | 
				
			||||||
 | 
					            keymap_str: CString::new("").unwrap(),
 | 
				
			||||||
 | 
					            kind: ArrangementKind::Base,
 | 
				
			||||||
 | 
					            locked_keys: HashSet::new(),
 | 
				
			||||||
 | 
					            pressed_keys: HashSet::new(),
 | 
				
			||||||
 | 
					            // Lots of bottom margin
 | 
				
			||||||
 | 
					            margins: Margins {
 | 
				
			||||||
 | 
					                top: 0.0,
 | 
				
			||||||
 | 
					                left: 0.0,
 | 
				
			||||||
 | 
					                right: 0.0,
 | 
				
			||||||
 | 
					                bottom: 1.0,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            views: hashmap! {
 | 
				
			||||||
 | 
					                String::new() => view,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            layout.calculate_inner_size(),
 | 
				
			||||||
 | 
					            Size { width: 1.0, height: 1.0 }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            layout.calculate_size(),
 | 
				
			||||||
 | 
					            Size { width: 1.0, height: 2.0 }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        // Don't change those values randomly!
 | 
				
			||||||
 | 
					        // They take advantage of incidental precise float representation
 | 
				
			||||||
 | 
					        // to even be comparable.
 | 
				
			||||||
 | 
					        let transformation = layout.calculate_transformation(
 | 
				
			||||||
 | 
					            Size { width: 2.0, height: 2.0 }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        assert_eq!(transformation.scale, 1.0);
 | 
				
			||||||
 | 
					        assert_eq!(transformation.origin_x, 0.5);
 | 
				
			||||||
 | 
					        assert_eq!(transformation.origin_y, 0.0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										9
									
								
								tests/layout_margins.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/layout_margins.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					# Margins present
 | 
				
			||||||
 | 
					margins: { top: 1, side: 2, bottom: 3 }
 | 
				
			||||||
 | 
					views:
 | 
				
			||||||
 | 
					    base:
 | 
				
			||||||
 | 
					        - "test"
 | 
				
			||||||
 | 
					outlines:
 | 
				
			||||||
 | 
					    default: { width: 1, height: 1 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								tests/layout_position.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/layout_position.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					# Margins present
 | 
				
			||||||
 | 
					margins: { top: 1, side: 2, bottom: 3 }
 | 
				
			||||||
 | 
					views:
 | 
				
			||||||
 | 
					    base:
 | 
				
			||||||
 | 
					        - "test"
 | 
				
			||||||
 | 
					outlines:
 | 
				
			||||||
 | 
					    default: { width: 1, height: 1 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reference in New Issue
	
	Block a user