147 lines
4.8 KiB
Rust
147 lines
4.8 KiB
Rust
mod exchange;
|
|
mod clock;
|
|
|
|
use exchange::{get_exchanges, Exchange};
|
|
use iced::widget::{column, container, row, text};
|
|
use iced::{Element, Length, Color, Theme, Subscription};
|
|
use chrono::{DateTime, Utc};
|
|
use std::time::Duration;
|
|
use std::path::Path;
|
|
|
|
pub fn main() -> iced::Result {
|
|
// Chargement propre de l'icône avec la crate `image`
|
|
let icon = if Path::new("clock.png").exists() {
|
|
match image::open("clock.png") {
|
|
Ok(img) => {
|
|
let rgba = img.to_rgba8();
|
|
let (width, height) = rgba.dimensions();
|
|
iced::window::icon::from_rgba(rgba.into_raw(), width, height).ok()
|
|
}
|
|
Err(_) => None,
|
|
}
|
|
} else {
|
|
None
|
|
};
|
|
|
|
iced::application(
|
|
"Horloges Boursières Mondiales",
|
|
WorldClocksApp::update,
|
|
WorldClocksApp::view,
|
|
)
|
|
.subscription(WorldClocksApp::subscription)
|
|
.window(iced::window::Settings {
|
|
size: iced::Size { width: 1700.0, height: 320.0 },
|
|
icon,
|
|
..Default::default()
|
|
})
|
|
.run_with(WorldClocksApp::new)
|
|
}
|
|
|
|
struct WorldClocksApp {
|
|
exchanges: Vec<Exchange>,
|
|
now: DateTime<Utc>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum Message {
|
|
Tick(DateTime<Utc>),
|
|
}
|
|
|
|
impl WorldClocksApp {
|
|
fn new() -> (Self, iced::Task<Message>) {
|
|
(
|
|
Self {
|
|
exchanges: get_exchanges(),
|
|
now: Utc::now(),
|
|
},
|
|
iced::Task::none(),
|
|
)
|
|
}
|
|
|
|
fn update(&mut self, message: Message) {
|
|
match message {
|
|
Message::Tick(time) => {
|
|
self.now = time;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn subscription(&self) -> Subscription<Message> {
|
|
iced::time::every(Duration::from_secs(1)).map(|_| Message::Tick(Utc::now()))
|
|
}
|
|
|
|
fn view(&self) -> Element<'_, Message> {
|
|
let mut row_layout = row![].spacing(10).padding(15);
|
|
|
|
for (i, exchange) in self.exchanges.iter().enumerate() {
|
|
let is_utc = i == 0;
|
|
let local_time = exchange.local_time(&self.now);
|
|
let time_str = local_time.format("%H:%M:%S").to_string();
|
|
|
|
// En-tête normalisé sur une hauteur fixe pour éviter tout décalage
|
|
let mut col = column![].spacing(4).align_x(iced::Alignment::Center);
|
|
|
|
if is_utc {
|
|
col = col.push(
|
|
text("UTC")
|
|
.size(13)
|
|
.style(|_theme: &Theme| text::Style { color: Some(Color::from_rgb(0.0, 0.8, 0.8)) })
|
|
);
|
|
// Espace vide invisible pour garder exactement la même hauteur que les lignes "ville + statut" des autres bourses
|
|
col = col.push(text(" ").size(11));
|
|
} else {
|
|
col = col.push(text(exchange.city.clone()).size(13));
|
|
let is_open = exchange.is_open(&self.now);
|
|
let (status_text, status_color) = if is_open {
|
|
("ouvert", Color::from_rgb(0.0, 0.8, 0.2))
|
|
} else {
|
|
("fermé", Color::from_rgb(0.9, 0.2, 0.2))
|
|
};
|
|
col = col.push(
|
|
text(status_text)
|
|
.size(11)
|
|
.style(move |_theme: &Theme| text::Style { color: Some(status_color) })
|
|
);
|
|
}
|
|
|
|
// Horloge analogique graphique
|
|
col = col.push(clock::view_clock(local_time));
|
|
|
|
// Horloge numérique
|
|
let digital_color = if is_utc { Color::from_rgb(0.0, 0.8, 0.8) } else { Color::WHITE };
|
|
col = col.push(
|
|
text(time_str)
|
|
.size(13)
|
|
.style(move |_theme: &Theme| text::Style { color: Some(digital_color) })
|
|
);
|
|
|
|
// Conteneur strict aux dimensions fixes absolues
|
|
let boxed_clock = container(col)
|
|
.width(Length::Fixed(155.0))
|
|
.height(Length::Fixed(230.0))
|
|
.padding(6)
|
|
.style(|_theme: &Theme| container::Style {
|
|
background: Some(iced::Background::Color(Color::from_rgb(0.12, 0.12, 0.15))),
|
|
border: iced::Border {
|
|
color: Color::from_rgb(0.25, 0.25, 0.3),
|
|
width: 1.0,
|
|
radius: 4.0.into(),
|
|
},
|
|
..Default::default()
|
|
});
|
|
|
|
row_layout = row_layout.push(boxed_clock);
|
|
}
|
|
|
|
container(row_layout)
|
|
.width(Length::Fill)
|
|
.height(Length::Fill)
|
|
.center_x(Length::Fill)
|
|
.center_y(Length::Fill)
|
|
.style(|_theme: &Theme| container::Style {
|
|
background: Some(iced::Background::Color(Color::from_rgb(0.08, 0.08, 0.1))),
|
|
..Default::default()
|
|
})
|
|
.into()
|
|
}
|
|
} |