Unverified Commit f8b29af6 authored by Andrey Azov's avatar Andrey Azov Committed by GitHub
Browse files

Refactor browser state (#107)

parent b415d868
Pipeline #25587 passed with stages
in 3 minutes and 43 seconds
......@@ -23,7 +23,6 @@ impl CombinedStickManager {
impl StickManager for CombinedStickManager {
fn get_stick(&mut self, name: &str) -> Option<Stick> {
console!("csm: {:?} ({:?})",name,self.internal.get(name).is_some());
if let Some(stick) = self.internal.get(name) {
Some(stick).cloned()
} else {
......
......@@ -96,10 +96,18 @@ impl Compositor {
}
pub fn update_report(&self, report: &Report) {
if let Some(stick) = self.train_manager.get_stick() {
report.set_status("i-stick",&stick.get_name());
}
self.train_manager.update_report(report);
}
pub fn set_stick(&mut self, st: &Stick) {
if let Some(stick) = self.train_manager.get_stick() {
if stick == st {
return;
}
}
self.prime_delay = None; // Force priming delay as screen is completely invalid
self.train_manager.set_stick(st,self.bp_per_screen);
self.psychic.set_stick(st);
......
......@@ -6,12 +6,10 @@ mod componentset;
mod landscape;
mod leaf;
pub mod source;
mod stage;
mod stick;
mod stickmanager;
mod zoom;
mod position;
mod wrapping;
mod stage;
pub use self::source::{
CombinedSource, Source, ActiveSource,
......@@ -33,8 +31,6 @@ pub use self::state::{
pub use self::leaf::Leaf;
pub use self::scale::Scale;
pub use self::zoom::Zoom;
pub use self::position::Position;
pub use self::wrapping::Wrapping;
pub use self::landscape::{ AllLandscapes, Landscape, Plot };
mod stage;
mod position;
mod zoom;
pub use self::stage::Stage;
\ No newline at end of file
use std::fmt;
use composit::Zoom;
use super::zoom::Zoom;
use types::{ Dot, Direction, LEFT, RIGHT, UP, DOWN, IN, OUT, AxisSense };
pub struct Position {
......@@ -11,7 +11,7 @@ pub struct Position {
min_x: f64,
max_x: f64,
min_x_bumper: f64,
max_x_bumper: f64,
max_x_bumper: f64
}
impl Position {
......@@ -25,12 +25,12 @@ impl Position {
}
}
pub fn inform_screen_size(&mut self, screen_size: &Dot<f64,f64>) {
pub(super) fn inform_screen_size(&mut self, screen_size: &Dot<f64,f64>) {
self.screen_size = *screen_size;
self.check_own_limits();
}
pub fn set_middle(&mut self, pos: &Dot<f64,f64>) {
pub(super) fn set_middle(&mut self, pos: &Dot<f64,f64>) {
bb_log!("resize","set_middle");
self.pos = *pos;
self.check_own_limits();
......@@ -48,19 +48,21 @@ impl Position {
self.zoom.get_screen_in_bp()
}
pub fn set_screen_in_bp(&mut self, zoom: f64) {
pub(super) fn set_screen_in_bp(&mut self, zoom: f64) {
self.zoom.set_screen_in_bp(zoom);
}
pub fn set_zoom(&mut self, z: f64) {
pub(super) fn set_zoom(&mut self, z: f64) {
self.zoom.set_zoom(z);
self.check_own_limits();
}
pub fn settle(&mut self) {
pub(super) fn settle(&mut self) {
return; /* temporary, degrades visual output but buggy */
bb_log!("resize","settle: screen width {}bp {}px",self.get_screen_in_bp(),self.screen_size.0);
if self.screen_size.0 > 0. {
let screen_px = self.screen_size.0.round() as i32;
let x_round = self.get_screen_in_bp() / screen_px as f64;;
let x_round = self.get_screen_in_bp() / screen_px as f64;
bb_log!("resize","round to {:?}bp",x_round);
self.pos.0 = (self.pos.0 / x_round).round() * x_round;
}
......@@ -92,8 +94,8 @@ impl Position {
}
}
pub fn get_limit_of_middle(&self, which: &Direction) -> f64 {
self.get_limit_of_edge(which) - self.middle_to_edge(which,true)
fn get_limit_of_middle(&self, which: &Direction) -> f64 {
self.get_limit_of_edge(which) - self.middle_to_edge(which,false)
}
pub fn get_limit_of_edge(&self, which: &Direction) -> f64 {
......@@ -125,7 +127,7 @@ impl Position {
self.zoom.set_max_bp(max_bp);
}
pub fn set_limit(&mut self, which: &Direction, val: f64) {
pub(super) fn set_limit(&mut self, which: &Direction, val: f64) {
match *which {
LEFT => self.min_x = val,
RIGHT => self.max_x = val,
......@@ -136,7 +138,7 @@ impl Position {
self.check_own_limits();
}
pub fn set_bumper(&mut self, which: &Direction, val: f64) {
pub(super) fn set_bumper(&mut self, which: &Direction, val: f64) {
match *which {
LEFT => self.min_x_bumper = val,
RIGHT => self.max_x_bumper = val,
......@@ -146,8 +148,8 @@ impl Position {
self.check_own_limits();
}
fn check_limits(&self, pos: &mut Dot<f64,f64>) {
/* minima always "win" when in conflict => max fn's called first */
fn check_limits(&mut self, pos: &mut Dot<f64,f64>) {
/* minima always "win" when in conflict => max fn's called first */
pos.0 = pos.0.min(self.get_limit_of_middle(&RIGHT));
pos.0 = pos.0.max(self.get_limit_of_middle(&LEFT));
pos.1 = pos.1.min(self.get_limit_of_middle(&DOWN));
......
use std::collections::HashMap;
use composit::{ Leaf, Position, Wrapping };
use composit::{ Leaf, Wrapping };
use controller::output::{ Report, ViewportReport };
use drivers::webgl::program::UniformValue;
use types::{
CPixel, Move, Dot, Direction,
LEFT, RIGHT, UP, DOWN, IN, OUT, XPosition, YPosition, Placement
};
use super::position::Position;
// XXX TODO avoid big-minus-big type calculations which accumulate error
......@@ -15,29 +16,45 @@ pub struct Stage {
dims: Dot<f64,f64>,
mouse_pos: CPixel,
base: f64,
pos: Position,
apos: Position,
ipos: Position,
valid_pos_intent: bool
}
impl Stage {
pub fn new() -> Stage {
let size = Dot(0.,0.);
Stage {
pos: Position::new(Dot(0.,0.),size),
apos: Position::new(Dot(0.,0.),size),
ipos: Position::new(Dot(0.,0.),size),
mouse_pos: Dot(0,0),
base: 0.,
dims: size,
valid_pos_intent: false
}
}
pub fn intend_here(&mut self) {
self.ipos.set_middle(&self.apos.get_middle());
self.ipos.set_zoom(self.apos.get_zoom());
}
pub fn set_pos_intent(&mut self, valid: bool) {
self.valid_pos_intent = valid;
}
fn bumped(&self, direction: &Direction) -> bool {
let mul : f64 = direction.1.into();
self.pos.get_edge(direction,true).floor() * mul >= self.pos.get_limit_of_edge(direction).floor() * mul
self.apos.get_edge(direction,true).floor() * mul >= self.apos.get_limit_of_edge(direction).floor() * mul
}
pub fn update_report(&self, report: &Report) {
let (left,right) = (self.pos.get_edge(&LEFT,true),self.pos.get_edge(&RIGHT,true));
report.set_status("start",&left.floor().to_string());
report.set_status("end",&right.ceil().to_string());
let (aleft,aright) = (self.apos.get_edge(&LEFT,false),self.apos.get_edge(&RIGHT,false));
report.set_status("a-start",&aleft.floor().to_string());
report.set_status("a-end",&aright.ceil().to_string());
let (ileft,iright) = (self.ipos.get_edge(&LEFT,false),self.ipos.get_edge(&RIGHT,false));
report.set_status("i-start",&ileft.floor().to_string());
report.set_status("i-end",&iright.ceil().to_string());
report.set_status_bool("bumper-left",self.bumped(&LEFT));
report.set_status_bool("bumper-right",self.bumped(&RIGHT));
report.set_status_bool("bumper-top",self.bumped(&UP));
......@@ -47,12 +64,14 @@ impl Stage {
}
pub fn update_viewport_report(&self, report: &ViewportReport) {
report.set_delta_y(-self.pos.get_edge(&UP,false) as i32);
report.set_delta_y(-self.apos.get_edge(&UP,false) as i32);
}
pub fn set_wrapping(&mut self, w: &Wrapping) {
self.pos.set_bumper(&LEFT,w.get_bumper(&LEFT));
self.pos.set_bumper(&RIGHT,w.get_bumper(&RIGHT));
self.apos.set_bumper(&LEFT,w.get_bumper(&LEFT));
self.apos.set_bumper(&RIGHT,w.get_bumper(&RIGHT));
self.ipos.set_bumper(&LEFT,w.get_bumper(&LEFT));
self.ipos.set_bumper(&RIGHT,w.get_bumper(&RIGHT));
}
pub fn set_mouse_pos(&mut self, c: &CPixel) {
......@@ -60,66 +79,57 @@ impl Stage {
}
pub fn set_screen_in_bp(&mut self, zoom: f64) {
self.pos.set_screen_in_bp(zoom);
self.apos.set_screen_in_bp(zoom);
self.ipos.set_screen_in_bp(zoom);
}
pub fn settle(&mut self) { self.pos.settle(); }
pub fn settle(&mut self) { self.apos.settle(); }
pub fn get_mouse_pos_prop(&self) -> f64 {
self.mouse_pos.0 as f64 / self.get_size().0 as f64
}
pub fn get_pos_prop_bp(&self, prop: f64) -> f64 {
let start = self.get_pos_middle().0 - self.pos.get_linear_zoom() / 2.;
start + prop * self.pos.get_linear_zoom()
fn get_pos_prop_bp(&self, prop: f64) -> f64 {
let start = self.get_pos_middle().0 - self.apos.get_linear_zoom() / 2.;
start + prop * self.apos.get_linear_zoom()
}
pub fn get_mouse_pos_bp(&self) -> f64 {
self.get_pos_prop_bp(self.get_mouse_pos_prop())
}
pub fn pos_prop_bp_to_origin(&self, pos: f64, prop: f64) -> f64 {
let start = pos - prop * self.pos.get_linear_zoom();
start + self.pos.get_linear_zoom()/2.
let start = pos - prop * self.apos.get_linear_zoom();
start + self.apos.get_linear_zoom()/2.
}
pub fn set_limit(&mut self, which: &Direction, val: f64) {
self.pos.set_limit(which,val);
self.apos.set_limit(which,val);
self.ipos.set_limit(which,val);
}
pub fn get_screen_in_bp(&self) -> f64 {
self.pos.get_screen_in_bp()
self.apos.get_screen_in_bp()
}
pub fn get_pos_middle(&self) -> Dot<f64,f64> {
self.pos.get_middle()
}
pub fn inc_pos(&mut self, delta: &Move<f64,f64>) {
let p = self.pos.get_middle() + *delta;
self.pos.set_middle(&p);
self.apos.get_middle()
}
pub fn set_zoom(&mut self, v: f64) {
self.pos.set_zoom(v);
}
pub fn inc_zoom(&mut self, by: f64) {
let z = self.pos.get_zoom() + by;
self.pos.set_zoom(z);
self.apos.set_zoom(v);
}
pub fn get_zoom(&self) -> f64 {
self.pos.get_zoom()
self.apos.get_zoom()
}
pub fn get_linear_zoom(&self) -> f64 {
self.pos.get_linear_zoom()
self.apos.get_linear_zoom()
}
pub fn set_pos_middle(&mut self, pos: &Dot<f64,f64>) {
self.pos.set_middle(pos);
self.apos.set_middle(pos);
}
pub fn get_size(&self) -> Dot<f64,f64> {
......@@ -128,14 +138,15 @@ impl Stage {
pub fn set_size(&mut self, size: &Dot<f64,f64>) {
self.dims = *size;
self.pos.inform_screen_size(size);
self.apos.inform_screen_size(size);
self.ipos.inform_screen_size(size);
}
pub fn get_uniforms(&self, leaf: &Leaf, opacity: f32) -> HashMap<&str,UniformValue> {
let bp_per_screen = self.pos.get_linear_zoom();
let bp_per_screen = self.apos.get_linear_zoom();
let bp_per_leaf = leaf.total_bp();
let leaf_per_screen = bp_per_screen as f64 / bp_per_leaf;
let middle_bp = self.pos.get_middle();
let middle_bp = self.apos.get_middle();
let middle_leaf = middle_bp.0/bp_per_leaf; // including fraction of leaf
let current_leaf_left = leaf.get_index() as f64;
hashmap! {
......@@ -153,8 +164,8 @@ impl Stage {
let screen_bp = self.get_screen_in_bp();
let screen_px = self.dims;
let bp_px = screen_bp / screen_px.0;
let left_bp = self.pos.get_edge(&LEFT,false);
let top_px = self.pos.get_edge(&UP,false);
let left_bp = self.apos.get_edge(&LEFT,false);
let top_px = self.apos.get_edge(&UP,false);
match area {
Placement::Stretch(r) => {
let pos_bp = left_bp + pos.0 as f64 * bp_px;
......
......@@ -40,7 +40,8 @@ pub struct App {
als: AllLandscapes,
size: Option<Dot<f64,f64>>,
last_resize_at: Option<f64>,
stage_resize: Option<Dot<f64,f64>>
stage_resize: Option<Dot<f64,f64>>,
action_backlog: Vec<Action>
}
impl App {
......@@ -71,14 +72,15 @@ impl App {
als: AllLandscapes::new(),
size: None,
stage_resize: None,
last_resize_at: None
last_resize_at: None,
action_backlog: Vec::new()
};
let dsm = {
let compo = &out.compo.lock().unwrap();
CombinedSourceManager::new(&tc,config,&compo.get_zmr(),&out.als,&out.http_clerk)
};
out.csl.add_compsource(Box::new(dsm));
out.run_actions(&startup_actions());
out.run_actions(&startup_actions(),None);
out
}
......@@ -172,8 +174,20 @@ impl App {
out
}
pub fn run_actions(self: &mut App, evs: &Vec<Action>) {
actions_run(self,evs);
pub fn run_actions(self: &mut App, evs: &Vec<Action>,currency: Option<f64>) {
if let Some(ref mut report) = self.report {
if currency.is_none() || report.is_current(currency.unwrap()) {
if self.action_backlog.len() > 0 {
console!("running backlog");
let backlog = self.action_backlog.drain(..).collect();
actions_run(self,&backlog,currency);
}
actions_run(self,evs,currency);
return;
}
}
console!("backlogging");
self.action_backlog.extend(evs.iter().cloned());
}
pub fn check_size(self: &mut App) {
......@@ -181,12 +195,12 @@ impl App {
let now = domutil::browser_time();
if self.size == None || self.size.unwrap() != sz {
self.last_resize_at = Some(now);
actions_run(self,&vec! { Action::Resize(sz) });
self.run_actions(&vec! { Action::Resize(sz) },None);
self.size = Some(sz);
}
if let Some(last_resize_at) = self.last_resize_at {
if now - last_resize_at > SETTLE_TIME {
actions_run(self,&vec! { Action::Settled });
self.run_actions(&vec! { Action::Settled },None);
self.last_resize_at = None;
}
}
......@@ -203,11 +217,26 @@ impl App {
self.printer.lock().unwrap().set_size(stage.get_size());
}
pub fn lock(&mut self) {
if let Some(ref mut report) = self.report {
report.lock();
}
}
pub fn unlock(&mut self) {
if let Some(ref mut report) = self.report {
report.unlock();
}
}
pub fn settle(&mut self) {
if let Some(size) = self.stage_resize.take() {
let mut stage = self.stage.lock().unwrap();
stage.set_size(&size);
}
let mut stage = self.stage.lock().unwrap();
stage.settle();
stage.intend_here();
self.printer.lock().unwrap().settle();
}
}
......@@ -143,7 +143,7 @@ impl Booting {
global.register_app_now(&self.key,ar.clone());
}
let app = ar.clone().state();
actions_run(&mut app.lock().unwrap(),&initial_actions());
app.lock().unwrap().run_actions(&initial_actions(),None);
self.ec.reset();
self.missed.run_missed(&mut app.lock().unwrap());
}
......
......@@ -42,7 +42,7 @@ fn exe_pos_range_event(app: &App, x_start: f64, x_end: f64, y: f64) {
let middle = Dot((x_start+x_end)/2.,y);
let (pos,zoom) = app.with_stage(|s| {
s.set_screen_in_bp(x_end-x_start);
s.set_pos_middle(&middle);
s.set_pos_middle(&middle);
(s.get_pos_middle(),s.get_linear_zoom())
});
app.with_compo(|co| {
......@@ -58,7 +58,7 @@ fn exe_move_event(app: &App, v: Move<f64,f64>) {
Axis::Vert => v.convert(Units::Pixels,s),
Axis::Zoom => v // TODO invalid pre-unification
};
s.inc_pos(&v);
s.set_pos_middle(&(s.get_pos_middle()+v));
s.get_pos_middle()
});
app.with_compo(|co| {
......@@ -66,13 +66,14 @@ fn exe_move_event(app: &App, v: Move<f64,f64>) {
});
}
fn exe_zoom_event(app: &App, z: f64, by: bool) {
fn exe_zoom_event(app: &App, za: f64, by: bool) {
let middle = app.with_stage(|s| s.get_pos_middle().0);
let z = app.with_stage(|s| {
if by {
s.inc_zoom(z);
let new_za = za+s.get_zoom();
s.set_zoom(new_za);
} else {
s.set_zoom(z);
s.set_zoom(za);
}
s.get_linear_zoom()
});
......@@ -98,13 +99,14 @@ fn exe_component_add(a: &mut App, name: &str) {
fn exe_set_stick(a: &mut App, name: &str) {
if let Some(stick) = a.with_stick_manager(|sm| sm.get_stick(name)) {
a.with_compo(|co| co.set_stick(&stick));
a.with_stage(|s| {
s.set_limit(&LEFT,0.);
s.set_limit(&RIGHT,stick.length() as f64);
s.set_wrapping(&stick.get_wrapping());
s.set_pos_intent(false);
});
a.with_compo(|co| co.set_stick(&stick));
exe_pos_event(a,cdfraction(0.,0.),None);
} else {
console_force!("NO SUCH STICK {}",name);
......@@ -117,14 +119,14 @@ fn exe_set_state(a: &mut App, name: &str, on: bool) {
});
}
fn exe_zmenu(a: &mut App, pos: &CPixel) {
fn exe_zmenu(a: &mut App, pos: &CPixel, currency: Option<f64>) {
console!("click {:?}",pos);
let acts = a.with_compo(|co|
a.with_stage(|s|
co.intersects(s,*pos)
)
);
actions_run(a,&acts);
a.run_actions(&acts,currency);
}
fn exe_deactivate(a: &mut App) {
......@@ -139,7 +141,8 @@ fn exe_zmenu_show(a: &mut App, id: &str, pos: Dot<i32,i32>, payload: JSONValue)
}
}
pub fn actions_run(cg: &mut App, evs: &Vec<Action>) {
pub fn actions_run(cg: &mut App, evs: &Vec<Action>, currency: Option<f64>) {
cg.lock();
for ev in evs {
let ev = ev.clone();
if ev.active() {
......@@ -148,19 +151,20 @@ pub fn actions_run(cg: &mut App, evs: &Vec<Action>) {
match ev {
Action::Pos(v,prop) => exe_pos_event(cg,v,prop),
Action::PosRange(x_start,x_end,y) => exe_pos_range_event(cg,x_start,x_end,y),
Action::Move(v) => exe_move_event(cg,v),
Action::Zoom(z) => exe_zoom_event(cg,z,true),
Action::ZoomTo(z) => exe_zoom_event(cg,z,false),
Action::Move(va) => exe_move_event(cg,va),
Action::Zoom(za) => exe_zoom_event(cg,za,true),
Action::ZoomTo(za) => exe_zoom_event(cg,za,false),
Action::Resize(sz) => exe_resize(cg,sz),
Action::AddComponent(name) => exe_component_add(cg,&name),
Action::SetStick(name) => exe_set_stick(cg,&name),
Action::SetState(name,on) => exe_set_state(cg,&name,on),
Action::Settled => exe_settled(cg),
Action::ZMenu(pos) => exe_zmenu(cg,&pos),
Action::ZMenu(pos) => exe_zmenu(cg,&pos,currency),
Action::ShowZMenu(id,pos,payload) => exe_zmenu_show(cg,&id,pos,payload),
Action::Noop => ()
}
}
cg.unlock();
}
pub fn startup_actions() -> Vec<Action> {
......
use std::convert::TryInto;
use std::sync::{ Arc, Mutex };
use serde_json::from_str;
use serde_json::Value as JSONValue;
use serde_json::Number as JSONNumber;
use stdweb::web::{ Element, HtmlElement };
use controller::global::{ App, AppRunner };
......@@ -20,13 +24,14 @@ fn custom_movement_event(dir: &str, unit: &str, v: &JSONValue) -> Action {
"screen"|"screens"|"sc" => Units::Screens,
_ => { return Action::Noop; }
};
Action::Move(match dir {
let act = match dir {