Impelemented zooming and slightly better scrolling.

This commit is contained in:
eschweic 2013-06-05 15:35:53 -07:00
parent fb2ce2c00c
commit 160f58e90a
3 changed files with 86 additions and 10 deletions

View file

@ -126,6 +126,9 @@ fn run_main_loop(port: Port<Msg>,
let page_size = @mut Size2D(0f32, 0f32);
let window_size = @mut Size2D(800, 600);
// Keeps track of the current zoom factor
let world_zoom = @mut 1f32;
let check_for_messages: @fn() = || {
// Periodically check if the script task responded to our last resize event
resize_rate_limiter.check_resize_response();
@ -248,16 +251,65 @@ fn run_main_loop(port: Port<Msg>,
*world_offset = world_offset_copy - delta;
// Clamp the world offset to the screen size.
let max_x = (page_size.width - window_size.width as f32).max(&0.0);
let max_x = (page_size.width * *world_zoom - window_size.width as f32).max(&0.0);
world_offset.x = world_offset.x.clamp(&0.0, &max_x);
let max_y = (page_size.height - window_size.height as f32).max(&0.0);
let max_y = (page_size.height * *world_zoom - window_size.height as f32).max(&0.0);
world_offset.y = world_offset.y.clamp(&0.0, &max_y);
debug!("compositor: scrolled to %?", *world_offset);
root_layer.common.set_transform(identity().translate(-world_offset.x,
-world_offset.y,
0.0));
let mut scroll_transform = identity();
scroll_transform = scroll_transform.translate(window_size.width as f32 / 2f32 * *world_zoom - world_offset.x,
window_size.height as f32 / 2f32 * *world_zoom - world_offset.y,
0.0);
scroll_transform = scroll_transform.scale(*world_zoom, *world_zoom, 1f32);
scroll_transform = scroll_transform.translate(window_size.width as f32 / -2f32,
window_size.height as f32 / -2f32,
0.0);
root_layer.common.set_transform(scroll_transform);
window.set_needs_display()
}
// When the user pinch-zooms, scale the layer
do window.set_zoom_callback |delta| {
let zoom_const = 0.01;
let old_world_zoom = *world_zoom;
// Determine zoom amount
*world_zoom = (*world_zoom + delta.y * zoom_const).max(&1.0);
// Update world offset
let corner_to_center_x = world_offset.x + window_size.width as f32 / 2f32;
let new_corner_to_center_x = corner_to_center_x * *world_zoom / old_world_zoom;
world_offset.x = world_offset.x + new_corner_to_center_x - corner_to_center_x;
let corner_to_center_y = world_offset.y + window_size.height as f32 / 2f32;
let new_corner_to_center_y = corner_to_center_y * *world_zoom / old_world_zoom;
world_offset.y = world_offset.y + new_corner_to_center_y - corner_to_center_y;
// Clamp to page bounds when zooming out
let max_x = (page_size.width * *world_zoom - window_size.width as f32).max(&0.0);
world_offset.x = world_offset.x.clamp(&0.0, &max_x);
let max_y = (page_size.height * *world_zoom - window_size.height as f32).max(&0.0);
world_offset.y = world_offset.y.clamp(&0.0, &max_y);
// Apply transformations
let mut zoom_transform = identity();
zoom_transform = zoom_transform.translate(window_size.width as f32 / 2f32 * *world_zoom - world_offset.x,
window_size.height as f32 / 2f32 * *world_zoom - world_offset.y,
0.0);
zoom_transform = zoom_transform.scale(*world_zoom, *world_zoom, 1f32);
zoom_transform = zoom_transform.translate(window_size.width as f32 / -2f32,
window_size.height as f32 / -2f32,
0.0);
root_layer.common.set_transform(zoom_transform);
window.set_needs_display()
}

View file

@ -8,7 +8,7 @@
/// least on desktops. It is designed for testing Servo without the need of a UI.
use windowing::{ApplicationMethods, CompositeCallback, LoadUrlCallback, ClickCallback};
use windowing::{ResizeCallback, ScrollCallback, WindowMethods};
use windowing::{ResizeCallback, ScrollCallback, ZoomCallback, WindowMethods};
use alert::{Alert, AlertMethods};
use core::libc::c_int;
@ -37,8 +37,10 @@ pub struct Window {
load_url_callback: Option<LoadUrlCallback>,
click_callback: Option<ClickCallback>,
scroll_callback: Option<ScrollCallback>,
zoom_callback: Option<ZoomCallback>,
drag_origin: Point2D<c_int>,
down_button: c_int
}
impl WindowMethods<Application> for Window {
@ -57,10 +59,14 @@ impl WindowMethods<Application> for Window {
load_url_callback: None,
click_callback: None,
scroll_callback: None,
zoom_callback: None,
drag_origin: Point2D(0, 0),
down_button: 0 // FIXME: Hacky solution to 2 button mouse.
// Replace with tkuehn's code.
};
// Register event handlers.
do glut::reshape_func(window.glut_window) |width, height| {
match window.resize_callback {
@ -78,8 +84,9 @@ impl WindowMethods<Application> for Window {
do glut::keyboard_func |key, _, _| {
window.handle_key(key)
}
do glut::mouse_func |_, _, x, y| {
do glut::mouse_func |button, _, x, y| {
window.handle_click(x, y);
window.down_button = button;
window.start_drag(x, y)
}
do glut::motion_func |x, y| {
@ -124,6 +131,11 @@ impl WindowMethods<Application> for Window {
self.scroll_callback = Some(new_scroll_callback)
}
/// Registers a zoom to be run when the user zooms.
pub fn set_zoom_callback(&mut self, new_zoom_callback: ZoomCallback) {
self.zoom_callback = Some(new_zoom_callback)
}
/// Spins the event loop.
pub fn check_loop(@mut self) {
glut::check_loop()
@ -163,9 +175,16 @@ impl Window {
let delta = new_point - self.drag_origin;
self.drag_origin = new_point;
match self.scroll_callback {
None => {}
Some(callback) => callback(Point2D(delta.x as f32, delta.y as f32)),
if self.down_button == 2 {
match self.zoom_callback {
None => {}
Some(callback) => callback(Point2D(delta.x as f32, delta.y as f32)),
}
} else {
match self.scroll_callback {
None => {}
Some(callback) => callback(Point2D(delta.x as f32, delta.y as f32)),
}
}
}

View file

@ -23,6 +23,9 @@ pub type ClickCallback = @fn(Point2D<f32>);
/// Type of the function that is called when the user scrolls.
pub type ScrollCallback = @fn(Point2D<f32>);
///Type of the function that is called when the user zooms.
pub type ZoomCallback = @fn(Point2D<f32>);
/// Methods for an abstract Application.
pub trait ApplicationMethods {
fn new() -> Self;
@ -46,6 +49,8 @@ pub trait WindowMethods<A> {
pub fn set_click_callback(&mut self, new_click_callback: ClickCallback);
/// Registers a callback to run when the user scrolls.
pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback);
/// Registers a callback to run when the user zooms.
pub fn set_zoom_callback(&mut self, new_zoom_callback: ZoomCallback);
/// Spins the event loop.
pub fn check_loop(@mut self);