2015-09-23 15:16:25 -04:00
|
|
|
|
|
|
|
use std::fs;
|
2015-09-25 09:00:49 -04:00
|
|
|
use std::thread;
|
|
|
|
use std::sync::mpsc;
|
|
|
|
use std::rc::Rc;
|
2015-09-25 09:48:35 -04:00
|
|
|
use std::cell::RefCell;
|
2015-09-25 09:00:49 -04:00
|
|
|
|
2015-09-23 15:16:25 -04:00
|
|
|
use ui;
|
|
|
|
use render;
|
|
|
|
use format;
|
2015-09-25 09:00:49 -04:00
|
|
|
use format::{Component, TextComponent};
|
|
|
|
use protocol;
|
|
|
|
|
2015-09-23 15:16:25 -04:00
|
|
|
use serde_json;
|
2015-09-25 09:00:49 -04:00
|
|
|
use time;
|
|
|
|
use image;
|
|
|
|
use rustc_serialize::base64::FromBase64;
|
|
|
|
use rand;
|
|
|
|
use rand::{Rng};
|
2015-09-23 15:16:25 -04:00
|
|
|
|
|
|
|
pub struct ServerList {
|
|
|
|
elements: Option<UIElements>,
|
2015-09-25 09:00:49 -04:00
|
|
|
disconnect_reason: Option<Component>,
|
2015-09-25 09:48:35 -04:00
|
|
|
|
|
|
|
needs_reload: Rc<RefCell<bool>>,
|
2015-09-23 15:16:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
struct UIElements {
|
|
|
|
logo: ui::logo::Logo,
|
|
|
|
elements: ui::Collection,
|
|
|
|
servers: Vec<Server>,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Server {
|
|
|
|
collection: ui::Collection,
|
|
|
|
back: ui::ElementRef<ui::Image>,
|
|
|
|
offset: f64,
|
|
|
|
y: f64,
|
2015-09-25 09:00:49 -04:00
|
|
|
|
|
|
|
motd: ui::ElementRef<ui::Formatted>,
|
|
|
|
ping: ui::ElementRef<ui::Image>,
|
|
|
|
players: ui::ElementRef<ui::Text>,
|
|
|
|
version: ui::ElementRef<ui::Formatted>,
|
|
|
|
|
|
|
|
icon: ui::ElementRef<ui::Image>,
|
|
|
|
icon_texture: Option<String>,
|
|
|
|
|
|
|
|
done_ping: bool,
|
|
|
|
recv: mpsc::Receiver<PingInfo>,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct PingInfo {
|
|
|
|
motd: format::Component,
|
|
|
|
ping: time::Duration,
|
|
|
|
exists: bool,
|
|
|
|
online: i32,
|
|
|
|
max: i32,
|
|
|
|
protocol_version: i32,
|
|
|
|
protocol_name: String,
|
|
|
|
favicon: Option<image::DynamicImage>,
|
2015-09-23 15:16:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Server {
|
|
|
|
fn update_position(&mut self) {
|
|
|
|
if self.offset < 0.0 {
|
|
|
|
self.y = self.offset * 200.0;
|
|
|
|
} else {
|
|
|
|
self.y = self.offset * 100.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ServerList {
|
2015-09-25 09:00:49 -04:00
|
|
|
pub fn new(disconnect_reason: Option<Component>) -> ServerList {
|
2015-09-23 15:16:25 -04:00
|
|
|
ServerList {
|
|
|
|
elements: None,
|
|
|
|
disconnect_reason: disconnect_reason,
|
2015-09-25 09:48:35 -04:00
|
|
|
needs_reload: Rc::new(RefCell::new(false)),
|
2015-09-23 15:16:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reload_server_list(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
|
|
|
let elements = self.elements.as_mut().unwrap();
|
2015-09-25 09:48:35 -04:00
|
|
|
*self.needs_reload.borrow_mut() = false;
|
2015-09-25 09:00:49 -04:00
|
|
|
{
|
|
|
|
let mut tex = renderer.get_textures_ref().write().unwrap();
|
|
|
|
for server in &mut elements.servers {
|
|
|
|
server.collection.remove_all(ui_container);
|
|
|
|
if let Some(ref icon) = server.icon_texture {
|
|
|
|
tex.remove_dynamic("steven_icon", &icon);
|
|
|
|
}
|
|
|
|
}
|
2015-09-23 15:16:25 -04:00
|
|
|
}
|
|
|
|
elements.servers.clear();
|
|
|
|
|
|
|
|
let file = match fs::File::open("servers.json") {
|
|
|
|
Ok(val) => val,
|
2015-09-25 09:00:49 -04:00
|
|
|
Err(_) => return,
|
2015-09-23 15:16:25 -04:00
|
|
|
};
|
|
|
|
let servers_info: serde_json::Value = serde_json::from_reader(file).unwrap();
|
|
|
|
let servers = servers_info.find("servers").unwrap().as_array().unwrap();
|
|
|
|
let mut offset = 0.0;
|
|
|
|
|
|
|
|
let default_icon = render::Renderer::get_texture(renderer.get_textures_ref(), "misc/unknown_server");
|
|
|
|
let icons = render::Renderer::get_texture(renderer.get_textures_ref(), "gui/icons");
|
|
|
|
|
|
|
|
for svr in servers {
|
|
|
|
let name = svr.find("name").unwrap().as_string().unwrap();
|
2015-09-25 09:00:49 -04:00
|
|
|
let address = svr.find("address").unwrap().as_string().unwrap().to_owned();
|
2015-09-23 15:16:25 -04:00
|
|
|
|
|
|
|
let solid = render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid");
|
|
|
|
|
|
|
|
let mut back = ui::Image::new(solid, 0.0, offset * 100.0, 700.0, 100.0, 0.0, 0.0, 1.0, 1.0, 0, 0, 0);
|
|
|
|
back.set_a(100);
|
|
|
|
back.set_v_attach(ui::VAttach::Middle);
|
|
|
|
back.set_h_attach(ui::HAttach::Center);
|
|
|
|
|
2015-09-25 09:00:49 -04:00
|
|
|
let (send, recv) = mpsc::channel::<PingInfo>();
|
2015-09-23 15:16:25 -04:00
|
|
|
let mut server = Server {
|
|
|
|
collection: ui::Collection::new(),
|
|
|
|
back: ui_container.add(back),
|
|
|
|
offset: offset,
|
|
|
|
y: 0.0,
|
2015-09-25 09:00:49 -04:00
|
|
|
done_ping: false,
|
|
|
|
recv: recv,
|
|
|
|
|
|
|
|
motd: Default::default(),
|
|
|
|
ping: Default::default(),
|
|
|
|
players: Default::default(),
|
|
|
|
version: Default::default(),
|
|
|
|
|
|
|
|
icon: Default::default(),
|
|
|
|
icon_texture: None,
|
2015-09-23 15:16:25 -04:00
|
|
|
};
|
|
|
|
server.collection.add(server.back.clone());
|
|
|
|
server.update_position();
|
2015-09-25 09:00:49 -04:00
|
|
|
{
|
|
|
|
let back = ui_container.get_mut(&server.back);
|
|
|
|
let back_ref = server.back.clone();
|
|
|
|
let address = address.clone();
|
2015-09-25 09:48:35 -04:00
|
|
|
back.add_hover_func(Rc::new(move |over, screen_sys, renderer, ui_container| {
|
2015-09-25 09:00:49 -04:00
|
|
|
let back = ui_container.get_mut(&back_ref);
|
|
|
|
back.set_a(if over { 200 } else { 100 });
|
|
|
|
}));
|
|
|
|
|
2015-09-25 09:48:35 -04:00
|
|
|
back.add_click_func(Rc::new(move |screen_sys, renderer, ui_container| {
|
2015-09-25 09:00:49 -04:00
|
|
|
println!("Connecting to {}", address);
|
|
|
|
}));
|
|
|
|
}
|
2015-09-23 15:16:25 -04:00
|
|
|
|
|
|
|
let mut text = ui::Text::new(renderer, &name, 100.0, 5.0, 255, 255, 255);
|
|
|
|
text.set_parent(&server.back);
|
|
|
|
server.collection.add(ui_container.add(text));
|
|
|
|
|
|
|
|
let mut icon = ui::Image::new(default_icon.clone(), 5.0, 5.0, 90.0, 90.0, 0.0, 0.0, 1.0, 1.0, 255, 255, 255);
|
|
|
|
icon.set_parent(&server.back);
|
2015-09-25 09:00:49 -04:00
|
|
|
server.icon = server.collection.add(ui_container.add(icon));
|
2015-09-23 15:16:25 -04:00
|
|
|
|
|
|
|
let mut ping = ui::Image::new(icons.clone(), 5.0, 5.0, 20.0, 16.0, 0.0, 56.0/256.0, 10.0/256.0, 8.0/256.0, 255, 255, 255);
|
|
|
|
ping.set_h_attach(ui::HAttach::Right);
|
|
|
|
ping.set_parent(&server.back);
|
2015-09-25 09:00:49 -04:00
|
|
|
server.ping = server.collection.add(ui_container.add(ping));
|
2015-09-23 15:16:25 -04:00
|
|
|
|
|
|
|
let mut players = ui::Text::new(renderer, "???", 30.0, 5.0, 255, 255, 255);
|
|
|
|
players.set_h_attach(ui::HAttach::Right);
|
|
|
|
players.set_parent(&server.back);
|
2015-09-25 09:00:49 -04:00
|
|
|
server.players = server.collection.add(ui_container.add(players));
|
|
|
|
|
|
|
|
let mut motd = ui::Formatted::with_width_limit(renderer, Component::Text(TextComponent::new("Connecting...")), 100.0, 23.0, 700.0 - (90.0 + 10.0 + 5.0));
|
|
|
|
motd.set_parent(&server.back);
|
|
|
|
server.motd = server.collection.add(ui_container.add(motd));
|
|
|
|
|
|
|
|
let mut version = ui::Formatted::with_width_limit(renderer, Component::Text(TextComponent::new("")), 100.0, 5.0, 700.0 - (90.0 + 10.0 + 5.0));
|
|
|
|
version.set_v_attach(ui::VAttach::Bottom);
|
|
|
|
version.set_parent(&server.back);
|
|
|
|
server.version = server.collection.add(ui_container.add(version));
|
|
|
|
|
|
|
|
|
|
|
|
let (mut del, mut txt) = super::new_button_text(renderer, "X", 0.0, 0.0, 25.0, 25.0);
|
|
|
|
del.set_v_attach(ui::VAttach::Bottom);
|
|
|
|
del.set_h_attach(ui::HAttach::Right);
|
|
|
|
del.set_parent(&server.back);
|
|
|
|
let re = ui_container.add(del);
|
|
|
|
txt.set_parent(&re);
|
|
|
|
let tre = ui_container.add(txt);
|
|
|
|
super::button_action(ui_container, re.clone(), Some(tre.clone()), None);
|
|
|
|
server.collection.add(re);
|
|
|
|
server.collection.add(tre);
|
|
|
|
|
|
|
|
let (mut edit, mut txt) = super::new_button_text(renderer, "E", 25.0, 0.0, 25.0, 25.0);
|
|
|
|
edit.set_v_attach(ui::VAttach::Bottom);
|
|
|
|
edit.set_h_attach(ui::HAttach::Right);
|
|
|
|
edit.set_parent(&server.back);
|
|
|
|
let re = ui_container.add(edit);
|
|
|
|
txt.set_parent(&re);
|
|
|
|
let tre = ui_container.add(txt);
|
|
|
|
super::button_action(ui_container, re.clone(), Some(tre.clone()), None);
|
|
|
|
server.collection.add(re);
|
|
|
|
server.collection.add(tre);
|
2015-09-23 15:16:25 -04:00
|
|
|
|
|
|
|
elements.servers.push(server);
|
|
|
|
offset += 1.0;
|
2015-09-25 09:00:49 -04:00
|
|
|
|
|
|
|
thread::spawn(move || {
|
|
|
|
match protocol::Conn::new(&address).and_then(|conn| conn.do_status()) {
|
|
|
|
Ok(res) => {
|
|
|
|
let mut desc = res.0.description;
|
|
|
|
format::convert_legacy(&mut desc);
|
|
|
|
let favicon = if let Some(icon) = res.0.favicon {
|
|
|
|
let data = icon["data:image/png;base64,".len()..].from_base64().unwrap();
|
|
|
|
Some(image::load_from_memory(
|
|
|
|
&data
|
|
|
|
).unwrap())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
send.send(PingInfo {
|
|
|
|
motd: desc,
|
|
|
|
ping: res.1,
|
|
|
|
exists: true,
|
|
|
|
online: res.0.players.online,
|
|
|
|
max: res.0.players.max,
|
|
|
|
protocol_version: res.0.version.protocol,
|
|
|
|
protocol_name: res.0.version.name,
|
|
|
|
favicon: favicon,
|
|
|
|
}).unwrap();
|
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
let e = format!("{}", err);
|
|
|
|
let mut msg = TextComponent::new(&e);
|
|
|
|
msg.modifier.color = Some(format::Color::Red);
|
|
|
|
send.send(PingInfo {
|
|
|
|
motd: Component::Text(msg),
|
|
|
|
ping: time::Duration::seconds(99999),
|
|
|
|
exists: false,
|
|
|
|
online: 0,
|
|
|
|
max: 0,
|
|
|
|
protocol_version: 0,
|
|
|
|
protocol_name: "".to_owned(),
|
|
|
|
favicon: None,
|
|
|
|
}).unwrap();
|
|
|
|
},
|
|
|
|
}
|
|
|
|
});
|
2015-09-23 15:16:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl super::Screen for ServerList {
|
|
|
|
fn init(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {}
|
|
|
|
fn deinit(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {}
|
|
|
|
|
|
|
|
fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
|
|
|
let logo = ui::logo::Logo::new(renderer.resources.clone(), renderer, ui_container);
|
|
|
|
let mut elements = ui::Collection::new();
|
|
|
|
|
|
|
|
let (mut refresh, mut txt) = super::new_button_text(renderer, "Refresh", 300.0, -50.0-15.0, 100.0, 30.0);
|
|
|
|
refresh.set_v_attach(ui::VAttach::Middle);
|
|
|
|
refresh.set_h_attach(ui::HAttach::Center);
|
|
|
|
let re = ui_container.add(refresh);
|
|
|
|
txt.set_parent(&re);
|
2015-09-25 09:00:49 -04:00
|
|
|
let tre = ui_container.add(txt);
|
2015-09-25 09:48:35 -04:00
|
|
|
let nr = self.needs_reload.clone();
|
|
|
|
super::button_action(ui_container, re.clone(), Some(tre.clone()), Some(Rc::new(move |screen_sys, renderer, ui_container| {
|
|
|
|
*nr.borrow_mut() = true;
|
|
|
|
})));
|
2015-09-23 15:16:25 -04:00
|
|
|
elements.add(re);
|
2015-09-25 09:00:49 -04:00
|
|
|
elements.add(tre);
|
2015-09-23 15:16:25 -04:00
|
|
|
|
|
|
|
let (mut add, mut txt) = super::new_button_text(renderer, "Add", 200.0, -50.0-15.0, 100.0, 30.0);
|
|
|
|
add.set_v_attach(ui::VAttach::Middle);
|
|
|
|
add.set_h_attach(ui::HAttach::Center);
|
|
|
|
let re = ui_container.add(add);
|
|
|
|
txt.set_parent(&re);
|
2015-09-25 09:00:49 -04:00
|
|
|
let tre = ui_container.add(txt);
|
2015-09-25 09:48:35 -04:00
|
|
|
super::button_action(ui_container, re.clone(), Some(tre.clone()), None);
|
2015-09-23 15:16:25 -04:00
|
|
|
elements.add(re);
|
2015-09-25 09:00:49 -04:00
|
|
|
elements.add(tre);
|
2015-09-23 15:16:25 -04:00
|
|
|
|
|
|
|
let mut options = super::new_button(renderer, 5.0, 25.0, 40.0, 40.0);
|
|
|
|
options.set_v_attach(ui::VAttach::Bottom);
|
|
|
|
options.set_h_attach(ui::HAttach::Right);
|
|
|
|
let re = ui_container.add(options);
|
|
|
|
let mut cog = ui::Image::new(render::Renderer::get_texture(renderer.get_textures_ref(), "steven:gui/cog"), 0.0, 0.0, 40.0, 40.0, 0.0, 0.0, 1.0, 1.0, 255, 255, 255);
|
|
|
|
cog.set_parent(&re);
|
|
|
|
cog.set_v_attach(ui::VAttach::Middle);
|
|
|
|
cog.set_h_attach(ui::HAttach::Center);
|
2015-09-25 09:00:49 -04:00
|
|
|
super::button_action(ui_container, re.clone(), None, None);
|
2015-09-23 15:16:25 -04:00
|
|
|
elements.add(re);
|
|
|
|
elements.add(ui_container.add(cog));
|
|
|
|
|
|
|
|
let mut warn = ui::Text::new(renderer, "Not affiliated with Mojang/Minecraft", 5.0, 5.0, 255, 200, 200);
|
|
|
|
warn.set_v_attach(ui::VAttach::Bottom);
|
|
|
|
warn.set_h_attach(ui::HAttach::Right);
|
|
|
|
elements.add(ui_container.add(warn));
|
|
|
|
|
|
|
|
if let Some(ref disconnect_reason) = self.disconnect_reason {
|
|
|
|
let mut dis_msg = ui::Text::new(renderer, "Disconnected", 0.0, 32.0, 255, 0, 0);
|
|
|
|
dis_msg.set_h_attach(ui::HAttach::Center);
|
|
|
|
let mut dis = ui::Formatted::with_width_limit(renderer, disconnect_reason.clone(), 0.0, 48.0, 600.0);
|
|
|
|
dis.set_h_attach(ui::HAttach::Center);
|
|
|
|
let mut back = ui::Image::new(
|
|
|
|
render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"),
|
|
|
|
0.0, 30.0,
|
|
|
|
dis.get_width().max(dis_msg.get_width()) + 4.0, dis.get_height() + 4.0 + 16.0,
|
|
|
|
0.0, 0.0, 1.0, 1.0,
|
|
|
|
0, 0, 0
|
|
|
|
);
|
|
|
|
back.set_a(100);
|
|
|
|
back.set_h_attach(ui::HAttach::Center);
|
|
|
|
elements.add(ui_container.add(back));
|
|
|
|
elements.add(ui_container.add(dis));
|
|
|
|
elements.add(ui_container.add(dis_msg));
|
|
|
|
}
|
|
|
|
|
|
|
|
self.elements = Some(UIElements {
|
|
|
|
logo: logo,
|
|
|
|
elements: elements,
|
|
|
|
servers: Vec::new(),
|
|
|
|
});
|
|
|
|
self.reload_server_list(renderer, ui_container);
|
|
|
|
}
|
|
|
|
fn on_deactive(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
|
|
|
{
|
|
|
|
let elements = self.elements.as_mut().unwrap();
|
|
|
|
elements.logo.remove(ui_container);
|
|
|
|
elements.elements.remove_all(ui_container);
|
|
|
|
for server in &mut elements.servers {
|
|
|
|
server.collection.remove_all(ui_container);
|
|
|
|
}
|
|
|
|
elements.servers.clear();
|
|
|
|
}
|
|
|
|
self.elements = None
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tick(&mut self, delta: f64, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
2015-09-25 09:48:35 -04:00
|
|
|
if *self.needs_reload.borrow() {
|
|
|
|
self.reload_server_list(renderer, ui_container);
|
|
|
|
}
|
2015-09-23 15:16:25 -04:00
|
|
|
let elements = self.elements.as_mut().unwrap();
|
2015-09-25 09:48:35 -04:00
|
|
|
|
2015-09-23 15:16:25 -04:00
|
|
|
elements.logo.tick(renderer, ui_container);
|
|
|
|
|
|
|
|
for s in &mut elements.servers {
|
2015-09-25 09:00:49 -04:00
|
|
|
{
|
|
|
|
let back = ui_container.get_mut(&s.back);
|
|
|
|
let dy = s.y - back.get_y();
|
|
|
|
if dy*dy > 1.0 {
|
|
|
|
let y = back.get_y();
|
|
|
|
back.set_y(y + delta * dy * 0.1);
|
|
|
|
} else {
|
|
|
|
back.set_y(s.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !s.done_ping {
|
|
|
|
match s.recv.try_recv() {
|
|
|
|
Ok(res) => {
|
|
|
|
s.done_ping = true;
|
|
|
|
{
|
|
|
|
let motd = ui_container.get_mut(&s.motd);
|
|
|
|
motd.set_component(renderer, res.motd);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let ping = ui_container.get_mut(&s.ping);
|
|
|
|
let y = match res.ping.num_milliseconds() {
|
|
|
|
_x @ 0 ... 75 => 16.0 / 256.0,
|
|
|
|
_x @ 76 ... 150 => 24.0 / 256.0,
|
|
|
|
_x @ 151 ... 225 => 32.0 / 256.0,
|
|
|
|
_x @ 226 ... 350 => 40.0 / 256.0,
|
|
|
|
_x @ 351 ... 999 => 48.0 / 256.0,
|
|
|
|
_ => 56.0 / 256.0,
|
|
|
|
};
|
|
|
|
ping.set_t_y(y);
|
|
|
|
}
|
|
|
|
if res.exists {
|
|
|
|
{
|
|
|
|
let players = ui_container.get_mut(&s.players);
|
|
|
|
let txt = if res.protocol_version == protocol::SUPPORTED_PROTOCOL {
|
|
|
|
players.set_g(255);
|
|
|
|
players.set_b(255);
|
|
|
|
format!("{}/{}", res.online, res.max)
|
|
|
|
} else {
|
|
|
|
players.set_g(85);
|
|
|
|
players.set_b(85);
|
|
|
|
format!("Out of date {}/{}", res.online, res.max)
|
|
|
|
};
|
|
|
|
players.set_text(renderer, &txt);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let version = ui_container.get_mut(&s.version);
|
|
|
|
let mut txt = TextComponent::new(&res.protocol_name);
|
|
|
|
txt.modifier.color = Some(format::Color::Yellow);
|
|
|
|
let mut msg = Component::Text(txt);
|
|
|
|
format::convert_legacy(&mut msg);
|
|
|
|
version.set_component(renderer, msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(favicon) = res.favicon {
|
|
|
|
let name: String = rand::thread_rng().gen_ascii_chars().take(30).collect();
|
|
|
|
let tex = renderer.get_textures_ref();
|
|
|
|
s.icon_texture = Some(name.clone());
|
|
|
|
let icon_tex = tex.write().unwrap().put_dynamic("steven_icon", &name, favicon);
|
|
|
|
let icon = ui_container.get_mut(&s.icon);
|
|
|
|
icon.set_texture(icon_tex);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(mpsc::TryRecvError::Disconnected) => {
|
|
|
|
s.done_ping = true;
|
|
|
|
let motd = ui_container.get_mut(&s.motd);
|
|
|
|
let mut txt = TextComponent::new("Channel dropped");
|
|
|
|
txt.modifier.color = Some(format::Color::Red);
|
|
|
|
motd.set_component(renderer, Component::Text(txt));
|
|
|
|
},
|
|
|
|
_ => {}
|
|
|
|
}
|
2015-09-23 15:16:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn on_scroll(&mut self, x: f64, y: f64) {
|
|
|
|
let elements = self.elements.as_mut().unwrap();
|
|
|
|
if elements.servers.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let mut diff = y / 1.0;
|
|
|
|
{
|
|
|
|
let last = elements.servers.last().unwrap();
|
|
|
|
if last.offset+diff <= 2.0 {
|
|
|
|
diff = 2.0 - last.offset;
|
|
|
|
}
|
|
|
|
let first = elements.servers.first().unwrap();
|
|
|
|
if first.offset + diff >= 0.0 {
|
|
|
|
diff = -first.offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for s in &mut elements.servers {
|
|
|
|
s.offset += diff;
|
|
|
|
s.update_position();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|