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

Focus object change (#123)

parent bf9ab37b
Pipeline #32525 passed with stages
in 4 minutes and 7 seconds
......@@ -693,6 +693,7 @@ dependencies = [
"hsl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"misc_algorithms 0.1.1",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -1126,6 +1127,13 @@ dependencies = [
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "misc_algorithms"
version = "0.1.1"
dependencies = [
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "native-tls"
version = "0.2.3"
......@@ -2327,7 +2335,7 @@ name = "tánaiste"
version = "0.1.1"
dependencies = [
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
......
......@@ -18,6 +18,7 @@ url="*"
base64="*"
"t\u00E1naiste" = { version="0.1.1", path="../t\u00E1naiste" }
"misc_algorithms" = { version="0.1.1", path="../misc_algorithms" }
[build-dependencies]
webgl_generator = "*"
......
......@@ -11,7 +11,7 @@ DEST="$BASE/../../../../ensembl/static/browser"
cd $SRC
touch Cargo.lock # force build
if [ "$1" == "check" ] ; then
export RUSTFLAGS="--cfg=deploy --cfg=console"
export RUSTFLAGS="--cfg=deploy --cfg=console -A warnings"
else
export RUSTFLAGS="--cfg=deploy"
fi
......@@ -26,7 +26,7 @@ echo "WASMHASH=$WASMHASH"
WASMNAME="browser-$WASMHASH.wasm"
JSNAME="browser.js"
rm $DEST/*.js $DEST/*.wasm
rm -f $DEST/*.js $DEST/*.wasm
cp $SRC/target/deploy/hellostdweb.wasm $DEST/$WASMNAME
cp $SRC/target/deploy/hellostdweb.js $DEST/$JSNAME
sed -i -e "s~\"hellostdweb.wasm\"~\"/static/browser/$WASMNAME\"~g" $DEST/$JSNAME
use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use composit::{ Stick, StickManager };
use data::BackendStickManager;
pub struct CombinedStickManager {
struct CombinedStickManagerImpl {
backend: BackendStickManager,
internal: HashMap<String,Stick>
}
impl CombinedStickManager {
pub fn new(backend: BackendStickManager) -> CombinedStickManager {
CombinedStickManager {
impl CombinedStickManagerImpl {
fn new(backend: BackendStickManager) -> CombinedStickManagerImpl {
CombinedStickManagerImpl {
backend,
internal: HashMap::<String,Stick>::new()
}
}
pub fn add_internal_stick(&mut self, name: &str, stick: Stick) {
fn add_internal_stick(&mut self, name: &str, stick: Stick) {
self.internal.insert(name.to_string(),stick);
}
}
impl StickManager for CombinedStickManager {
fn get_stick(&mut self, name: &str) -> Option<Stick> {
if let Some(stick) = self.internal.get(name) {
Some(stick).cloned()
......@@ -30,3 +30,22 @@ impl StickManager for CombinedStickManager {
}
}
}
#[derive(Clone)]
pub struct CombinedStickManager(Rc<RefCell<CombinedStickManagerImpl>>);
impl CombinedStickManager {
pub fn new(backend: BackendStickManager) -> CombinedStickManager {
CombinedStickManager(Rc::new(RefCell::new(CombinedStickManagerImpl::new(backend))))
}
pub fn add_internal_stick(&mut self, name: &str, stick: Stick) {
self.0.borrow_mut().add_internal_stick(name,stick);
}
}
impl StickManager for CombinedStickManager {
fn get_stick(&mut self, name: &str) -> Option<Stick> {
self.0.borrow_mut().get_stick(name)
}
}
\ No newline at end of file
use std::collections::{ HashMap, HashSet };
use composit::ActiveSource;
use model::supply::Product;
#[derive(Clone)]
pub struct ComponentSet {
components: HashMap<String,ActiveSource>
components: HashMap<String,Product>
}
impl ComponentSet {
pub fn new() -> ComponentSet {
ComponentSet {
components: HashMap::<String,ActiveSource>::new()
components: HashMap::<String,Product>::new()
}
}
pub fn add(&mut self, comp: ActiveSource) {
self.components.insert(comp.get_name().to_string(),comp);
pub fn add(&mut self, comp: Product) {
self.components.insert(comp.get_product_name().to_string(),comp);
}
pub fn remove(&mut self, comp: ActiveSource) {
self.components.remove(comp.get_name());
pub fn remove(&mut self, comp: Product) {
self.components.remove(comp.get_product_name());
}
pub fn list_names(&self) -> Vec<String> {
self.components.keys().cloned().collect()
pub fn get_products(&self) -> impl Iterator<Item=&Product> {
self.components.values()
}
pub fn not_in(&self, other: &ComponentSet) -> Vec<ActiveSource> {
pub fn not_in(&self, other: &ComponentSet) -> Vec<Product> {
let our_keys : HashSet<String> = self.components.keys().cloned().collect();
let their_keys : HashSet<String> = other.components.keys().cloned().collect();
our_keys.difference(&their_keys).map(|x| self.components[x].clone()).collect()
......
use composit::{
ActiveSource, Stick, Scale, ComponentSet, StateManager, Stage
};
use std::collections::HashSet;
use composit::{ Stick, Scale, ComponentSet, StateManager, AllLandscapes };
use model::driver::{ PrinterManager, Printer };
use model::train::{ Train, TrainManager, TravellerCreator };
use drivers::zmenu::{ ZMenuRegistry, ZMenuLeafSet };
use model::stage::{ Screen, Position };
use model::supply::{ Product };
use model::train::{ Train, TrainContext, TrainManager, TravellerCreator };
use model::zmenu::{ ZMenuRegistry, ZMenuLeafSet, ZMenuIntersection };
use controller::global::AppRunner;
use controller::global::{ AppRunner, WindowState };
use controller::input::Action;
use controller::output::Report;
use data::{ Psychic, PsychicPacer, XferCache, XferClerk };
use data::{ Psychic, PsychicPacer, XferCache, XferClerk, XferConsumer };
use types::{ DOWN, Dot };
const MS_PER_UPDATE : f64 = 0.;
const MS_PER_UPDATE : f64 = 100.;
const MS_PRIME_DELAY: f64 = 2000.;
pub struct Compositor {
train_manager: TrainManager,
window: WindowState,
traveller_creator: TravellerCreator,
zmr: ZMenuRegistry,
bp_per_screen: f64,
updated: bool,
prime_delay: Option<f64>,
last_updated: Option<f64>,
components: TravellerCreator,
wanted_componentset: ComponentSet,
current_componentset: ComponentSet,
psychic: Psychic,
pacer: PsychicPacer,
xfercache: XferCache,
xferclerk: Box<XferClerk>
xfercache: XferCache
}
impl Compositor {
pub fn new(printer: PrinterManager, xfercache: &XferCache, xferclerk: Box<XferClerk>) -> Compositor {
pub fn new(window: &WindowState, traveller_creator: &TravellerCreator, xfercache: &XferCache) -> Compositor {
Compositor {
train_manager: TrainManager::new(&printer),
traveller_creator: traveller_creator.clone(),
window: window.clone(),
zmr: ZMenuRegistry::new(),
components: TravellerCreator::new(&printer),
bp_per_screen: 1.,
updated: true,
last_updated: None,
......@@ -45,14 +45,13 @@ impl Compositor {
psychic: Psychic::new(),
prime_delay: None,
pacer: PsychicPacer::new(30000.),
xfercache: xfercache.clone(),
xferclerk: xferclerk
xfercache: xfercache.clone()
}
}
pub fn get_zmr(&self) -> &ZMenuRegistry { &self.zmr }
pub fn get_prop_trans(&self) -> f32 { self.train_manager.get_prop_trans() }
pub fn get_prop_trans(&mut self) -> f32 { self.window.get_train_manager().get_prop_trans() }
fn prime_cache(&mut self, t: f64) {
if self.prime_delay.is_none() {
......@@ -62,8 +61,8 @@ impl Compositor {
if let Some(leafs) = self.psychic.get_leafs() {
let leafs = self.pacer.filter_leafs(leafs,t);
for leaf in leafs.iter() {
for comp in self.wanted_componentset.list_names() {
self.xfercache.prime(&mut self.xferclerk,&comp,&leaf);
for prod in self.wanted_componentset.get_products() {
self.xfercache.prime(self.window.get_http_clerk(),prod,&leaf);
}
}
}
......@@ -73,67 +72,62 @@ impl Compositor {
pub fn tick(&mut self, t: f64) {
/* Manage components */
for added in self.wanted_componentset.not_in(&self.current_componentset).iter() {
self.add_component(added.clone());
self.add_product(added.clone());
}
for removed in self.current_componentset.not_in(&self.wanted_componentset).iter() {
self.components.remove_source(removed.clone().get_name());
self.traveller_creator.remove_source(removed.clone().get_product_name());
}
self.current_componentset = self.wanted_componentset.clone();
/* Warm up xfercache */
self.prime_cache(t);
/* Move into future */
self.train_manager.tick(t,&mut self.components);
self.window.get_train_manager().tick(t);
/* Manage useful leafs */
if self.updated {
if let Some(prev_t) = self.last_updated {
if t-prev_t < MS_PER_UPDATE { return; }
}
let comps = &mut self.components;
self.train_manager.best_train(|sc| sc.manage_leafs(comps));
self.window.get_train_manager().manage_carriages();
self.updated = false;
self.last_updated = Some(t);
}
}
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 update_report(&mut self, report: &Report) {
self.window.get_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;
}
pub fn set_stick(&mut self, st: &Stick) -> bool {
if self.window.get_train_manager().set_desired_stick(st) {
self.prime_delay = None; // Force priming delay as screen is completely invalid
self.psychic.set_stick(st);
self.updated = true;
true
} else {
false
}
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);
self.updated = true;
}
pub fn set_position(&mut self, position_bp: f64) {
self.train_manager.set_position(position_bp);
self.psychic.set_middle(position_bp as i64);
pub fn set_position(&mut self, middle: Dot<f64,f64>) {
self.window.get_train_manager().set_middle(middle);
self.psychic.set_middle(middle.0 as i64);
self.updated = true;
}
pub fn set_zoom(&mut self, bp_per_screen: f64) {
pub fn set_bp_per_screen(&mut self, bp_per_screen: f64) {
self.bp_per_screen = bp_per_screen;
self.train_manager.set_zoom(&mut self.components, bp_per_screen);
self.window.get_train_manager().set_bp_per_screen(bp_per_screen);
self.psychic.set_scale(&Scale::best_for_screen(bp_per_screen));
self.psychic.set_width(bp_per_screen as i32);
self.updated = true;
}
pub fn get_current_train(&mut self) -> Option<&mut Train> {
self.train_manager.get_current_train()
pub fn with_current_train<F>(&mut self, mut cb: F) where F: FnMut(&mut Train) {
self.window.get_train_manager().with_current_train(cb)
}
pub fn get_transition_train(&mut self) -> Option<&mut Train> {
self.train_manager.get_transition_train()
pub fn with_transition_train<F>(&mut self, mut cb: F) where F: FnMut(&mut Train) {
self.window.get_train_manager().with_transition_train(cb)
}
pub fn get_component_set(&mut self) -> &mut ComponentSet {
......@@ -142,39 +136,32 @@ impl Compositor {
pub fn redraw_where_needed(&mut self, printer: &mut Printer) {
let mut zmls = ZMenuLeafSet::new();
if let Some(train) = self.get_current_train() {
train.redraw_where_needed(printer,&mut zmls);
}
if let Some(train) = self.get_transition_train() {
train.redraw_where_needed(printer,&mut zmls);
}
self.with_current_train(|train| train.redraw_where_needed(printer,&mut zmls));
self.with_transition_train(|train| train.redraw_where_needed(printer,&mut zmls));
self.zmr.add_leafset(zmls);
}
fn add_component(&mut self, mut c: ActiveSource) {
{
let cc = &mut self.components;
self.train_manager.each_train(|sc|
sc.add_component(cc,&mut c)
);
}
self.components.add_source(c);
fn add_product(&mut self, mut c: Product) {
self.window.get_train_manager().add_component(&mut c);
self.traveller_creator.add_source(c);
}
pub fn update_state(&mut self, oom: &StateManager) {
self.train_manager.update_state(oom);
self.window.get_train_manager().update_state(oom);
}
pub fn intersects(&self, stage: &Stage, pos: Dot<i32,i32>) -> Vec<Action> {
self.zmr.intersects(stage,pos)
pub fn intersects(&mut self, screen: &Screen, pos: Dot<i32,i32>) -> HashSet<ZMenuIntersection> {
let mut zmr = self.zmr.clone();
self.window.get_train_manager().intersects(screen,pos,&mut zmr)
}
}
pub fn register_compositor_ticks(ar: &mut AppRunner) {
ar.add_timer("compositor",|cs,t,_| {
cs.with_compo(|co| co.tick(t) );
let max_y = cs.get_all_landscapes().get_low_watermark();
cs.with_stage(|s| s.set_limit(&DOWN,max_y as f64));
ar.add_timer("compositor",|app,t,_| {
app.with_compo(|co| co.tick(t) );
let max_y = app.get_window().get_all_landscapes().get_low_watermark();
app.get_window().get_train_manager().set_bottom(max_y as f64);
app.update_position();
vec!{}
},2);
}
......@@ -7,12 +7,14 @@ use super::landscape::Landscape;
pub struct AllLandscapesImpl {
vs: ValueStore<Landscape>,
focus: Option<String>
}
impl AllLandscapesImpl {
fn new() -> AllLandscapesImpl {
AllLandscapesImpl {
vs: ValueStore::<Landscape>::new(),
focus: None
}
}
......@@ -26,7 +28,7 @@ impl AllLandscapesImpl {
self.vs.get_mut(lid).map(|ls| cb(ls))
}
pub fn every<F,G>(&mut self, mut cb: F) -> Vec<Option<G>>
fn every<F,G>(&mut self, mut cb: F) -> Vec<Option<G>>
where F: FnMut(usize, &mut Landscape) -> G {
let mut out = Vec::<Option<G>>::new();
let lids : Vec<usize> = self.vs.every().collect();
......@@ -36,7 +38,7 @@ impl AllLandscapesImpl {
out
}
pub fn get_low_watermark(&self) -> i32 {
fn get_low_watermark(&self) -> i32 {
let mut max = 0;
for lid in self.vs.every() {
if let Some(ls) = self.vs.get(lid) {
......
......@@ -15,6 +15,13 @@ impl Leaf {
Leaf { hindex, scale: scale.clone(), stick: stick.clone() }
}
pub fn from_short_spec(stick: &Stick, pane: &str) -> Leaf {
let mut pane = pane.to_string();
let hindex : i64 = ok!(pane.split_off(1).parse());
let scale = Scale::new_from_letter(unwrap!(pane.chars().next()));
Leaf::new(stick,hindex,&scale)
}
pub fn containing(stick: &Stick, pos: f64, scale: &Scale) -> Leaf {
let hindex = (pos / scale.total_bp()).floor() as i64;
Leaf::new(stick,hindex,scale)
......
......@@ -5,20 +5,13 @@ mod combinedstickmanager;
mod componentset;
mod landscape;
mod leaf;
pub mod source;
mod stick;
mod stickmanager;
mod wrapping;
mod stage;
pub use self::source::{
CombinedSource, Source, ActiveSource,
SourceManager, SourceManagerList, CombinedSourceManager
};
pub use self::combinedstickmanager::CombinedStickManager;
pub use self::componentset::ComponentSet;
pub use self::compositor::{ Compositor, register_compositor_ticks };
pub use self::stage::{ Stage };
pub use self::stick::Stick;
pub use self::stickmanager::StickManager;
......
......@@ -17,7 +17,7 @@ impl Scale {
}
pub fn new_from_letter(letter: char) -> Scale {
Scale::new(ZOOMCODES.find(letter).unwrap() as i32-13)
Scale::new(unwrap!(ZOOMCODES.find(letter)) as i32-13)
}
pub fn letter(&self) -> char {
......
use std::cmp::{ Eq, PartialEq };
use std::collections::HashMap;
use std::fmt;
use std::hash::{ Hash, Hasher };
use std::rc::Rc;
use composit::state::StateExpr;
use composit::{
AllLandscapes, Landscape, Source, Leaf,
StateManager
};
use model::driver::PrinterManager;
use drivers::zmenu::ZMenuRegistry;
use model::train::Traveller;
use composit::source::SourceResponse;
use super::SourcePart;
#[derive(Clone)]
pub struct ActiveSource {
als: AllLandscapes,
lid: usize,
name: String,
parts: HashMap<Option<String>,SourcePart>,
source: Rc<Source>,
zmr: ZMenuRegistry
}
impl ActiveSource {
pub fn new(name: &str, source: Rc<Source>, zmr: &ZMenuRegistry, als: &AllLandscapes, lid: usize) -> ActiveSource {
ActiveSource {
source, lid,
name: name.to_string(),
als: als.clone(),
parts: HashMap::<Option<String>,SourcePart>::new(),
zmr: zmr.clone()
}
}
pub fn get_source(&self) -> &Rc<Source> { &self.source }
pub fn new_part(&mut self, part: Option<&str>, ooe: Rc<StateExpr>) {
self.parts.insert(part.map(|x| x.to_string()),SourcePart::new(part,&ooe));
}
pub fn list_parts(&self) -> Vec<String> {
self.parts.keys().filter(|x| x.is_some()).map(|x| x.as_ref().unwrap().clone()).collect()
}
fn make_one_traveller(&self, part: &Option<String>, leaf: &Leaf) -> Traveller {
Traveller::new(self.clone(),part,leaf)
}
pub fn make_travellers(&mut self, leaf: &Leaf) -> Vec<Traveller> {
let mut out = Vec::<Traveller>::new();
/* create the travellers */
out.push(self.make_one_traveller(&None,&leaf));
for part in self.list_parts() {
out.push(self.make_one_traveller(&Some(part),&leaf));
}
out
}
pub fn request_data(&self, party: SourceResponse, leaf: &Leaf) {
let twin = self.source.clone();
twin.request_data(self,party,leaf);
}
pub fn get_name(&self) -> &str { &self.name }
pub fn is_on(&self, m: &StateManager, part: &Option<String>) -> bool {
self.parts.get(&part).unwrap().is_on(m)
}
pub fn with_landscape<F,G>(&mut self, lid: usize, cb: F) -> Option<G>
where F: FnOnce(&mut Landscape) -> G {
self.als.with(lid,cb)
}
pub fn with_zmr<F,G>(&mut self, cb: F) -> G
where F: FnOnce(&mut ZMenuRegistry) -> G {
cb(&mut self.zmr)
}
pub fn all_landscapes<F,G>(&mut self, cb: F) -> Vec<Option<G>>
where F: Fn(usize,&mut Landscape) -> G {
self.als.every(cb)
}
}
impl PartialEq for ActiveSource {
fn eq(&self, other: &ActiveSource) -> bool {
self.name == other.name
}
}
impl Eq for ActiveSource {}