use std::ffi::{c_int, c_void};
use euroscope_sys::EsHandle;
use crate::{
Context, Controller, ControllerDataType, FlightPlan, Point, Position, RadarTarget, Rect,
RefreshPhase, SectorElement,
utils::{cstr, cstr_lossy},
};
#[derive(Clone, Copy)]
pub struct Hdc(*mut c_void);
impl Hdc {
pub(crate) fn from_raw(raw: *mut c_void) -> Self {
Self(raw)
}
pub fn as_raw(self) -> *mut c_void {
self.0
}
}
pub trait RadarScreen: 'static {
fn on_asr_content_loaded(&mut self, screen: &mut RadarScreenContext, loaded: bool) {
let _ = (screen, loaded);
}
fn on_asr_content_to_be_saved(&mut self, screen: &mut RadarScreenContext) {
let _ = screen;
}
fn on_refresh(&mut self, screen: &mut RadarScreenContext, hdc: Hdc, phase: RefreshPhase) {
let _ = (screen, hdc, phase);
}
fn on_compile_command(&mut self, screen: &mut RadarScreenContext, command: &str) -> bool {
let _ = (screen, command);
false
}
fn on_function_call(
&mut self,
screen: &mut RadarScreenContext,
function_id: i32,
item_string: &str,
point: Point,
area: Rect,
) {
let _ = (screen, function_id, item_string, point, area);
}
fn on_screen_object_over(
&mut self,
screen: &mut RadarScreenContext,
object_type: i32,
object_id: &str,
point: Point,
area: Rect,
) {
let _ = (screen, object_type, object_id, point, area);
}
fn on_screen_object_button_down(
&mut self,
screen: &mut RadarScreenContext,
object_type: i32,
object_id: &str,
point: Point,
area: Rect,
button: crate::MouseButton,
) {
let _ = (screen, object_type, object_id, point, area, button);
}
fn on_screen_object_button_up(
&mut self,
screen: &mut RadarScreenContext,
object_type: i32,
object_id: &str,
point: Point,
area: Rect,
button: crate::MouseButton,
) {
let _ = (screen, object_type, object_id, point, area, button);
}
fn on_screen_object_click(
&mut self,
screen: &mut RadarScreenContext,
object_type: i32,
object_id: &str,
point: Point,
area: Rect,
button: crate::MouseButton,
) {
let _ = (screen, object_type, object_id, point, area, button);
}
fn on_screen_object_double_click(
&mut self,
screen: &mut RadarScreenContext,
object_type: i32,
object_id: &str,
point: Point,
area: Rect,
button: crate::MouseButton,
) {
let _ = (screen, object_type, object_id, point, area, button);
}
fn on_screen_object_move(
&mut self,
screen: &mut RadarScreenContext,
object_type: i32,
object_id: &str,
point: Point,
area: Rect,
released: bool,
) {
let _ = (screen, object_type, object_id, point, area, released);
}
fn on_controller_position_update(
&mut self,
screen: &mut RadarScreenContext,
controller: Controller<'_>,
) {
let _ = (screen, controller);
}
fn on_controller_disconnect(
&mut self,
screen: &mut RadarScreenContext,
controller: Controller<'_>,
) {
let _ = (screen, controller);
}
fn on_radar_target_position_update(
&mut self,
screen: &mut RadarScreenContext,
radar_target: RadarTarget<'_>,
) {
let _ = (screen, radar_target);
}
fn on_flight_plan_disconnect(
&mut self,
screen: &mut RadarScreenContext,
flight_plan: FlightPlan<'_>,
) {
let _ = (screen, flight_plan);
}
fn on_flight_plan_data_update(
&mut self,
screen: &mut RadarScreenContext,
flight_plan: FlightPlan<'_>,
) {
let _ = (screen, flight_plan);
}
fn on_controller_assigned_data_update(
&mut self,
screen: &mut RadarScreenContext,
flight_plan: FlightPlan<'_>,
data_type: ControllerDataType,
) {
let _ = (screen, flight_plan, data_type);
}
fn on_flight_strip_pushed(
&mut self,
screen: &mut RadarScreenContext,
flight_plan: FlightPlan<'_>,
sender: &str,
target: &str,
) {
let _ = (screen, flight_plan, sender, target);
}
}
pub struct RadarScreenContext {
raw: EsHandle,
}
type RectFn = unsafe extern "C" fn(EsHandle, *mut c_int, *mut c_int, *mut c_int, *mut c_int);
impl RadarScreenContext {
pub(crate) fn from_raw(raw: EsHandle) -> Self {
Self { raw }
}
pub(crate) fn as_ptr(&self) -> EsHandle {
self.raw
}
fn rect(&self, f: RectFn) -> Rect {
let (mut l, mut t, mut r, mut b) = (0_i32, 0_i32, 0_i32, 0_i32);
unsafe {
f(self.raw, &raw mut l, &raw mut t, &raw mut r, &raw mut b);
}
Rect::new(l, t, r, b)
}
pub fn plugin(&self) -> Context {
Context::from_raw(unsafe { euroscope_sys::es_screen_get_plugin(self.raw) })
}
pub fn radar_area(&self) -> Rect {
self.rect(euroscope_sys::es_screen_radar_area)
}
pub fn toolbar_area(&self) -> Rect {
self.rect(euroscope_sys::es_screen_toolbar_area)
}
pub fn chat_area(&self) -> Rect {
self.rect(euroscope_sys::es_screen_chat_area)
}
pub fn position_to_pixel(&self, position: Position) -> Point {
let (mut x, mut y) = (0_i32, 0_i32);
unsafe {
euroscope_sys::es_screen_position_to_pixel(
self.raw,
position.latitude,
position.longitude,
&raw mut x,
&raw mut y,
);
}
Point::new(x, y)
}
pub fn pixel_to_position(&self, point: Point) -> Position {
let (mut lat, mut lon) = (0.0_f64, 0.0_f64);
unsafe {
euroscope_sys::es_screen_pixel_to_position(
self.raw,
point.x,
point.y,
&raw mut lat,
&raw mut lon,
);
}
Position::new(lat, lon)
}
pub fn add_screen_object(
&self,
object_type: i32,
object_id: &str,
area: Rect,
moveable: bool,
tooltip: &str,
) {
let object_id = cstr_lossy(object_id);
let tooltip = cstr_lossy(tooltip);
unsafe {
euroscope_sys::es_screen_add_screen_object(
self.raw,
object_type,
object_id.as_ptr(),
area.left,
area.top,
area.right,
area.bottom,
moveable,
tooltip.as_ptr(),
);
}
}
pub fn request_refresh(&self) {
unsafe { euroscope_sys::es_screen_request_refresh(self.raw) }
}
pub fn refresh_map_content(&self) {
unsafe { euroscope_sys::es_screen_refresh_map_content(self.raw) }
}
pub fn get_asr_data(&self, name: &str) -> Option<String> {
let name = cstr_lossy(name);
unsafe {
let s = cstr(euroscope_sys::es_screen_get_data_from_asr(
self.raw,
name.as_ptr(),
));
(!s.is_empty()).then(|| s.to_owned())
}
}
pub fn save_asr_data(&self, name: &str, description: &str, value: &str) {
let name = cstr_lossy(name);
let description = cstr_lossy(description);
let value = cstr_lossy(value);
unsafe {
euroscope_sys::es_screen_save_data_to_asr(
self.raw,
name.as_ptr(),
description.as_ptr(),
value.as_ptr(),
);
}
}
pub fn display_area(&self) -> (Position, Position) {
let (mut a, mut b, mut c, mut d) = (0.0_f64, 0.0_f64, 0.0_f64, 0.0_f64);
unsafe {
euroscope_sys::es_screen_get_display_area(
self.raw, &raw mut a, &raw mut b, &raw mut c, &raw mut d,
);
}
(Position::new(a, b), Position::new(c, d))
}
pub fn set_display_area(&self, left_down: Position, right_up: Position) {
unsafe {
euroscope_sys::es_screen_set_display_area(
self.raw,
left_down.latitude,
left_down.longitude,
right_up.latitude,
right_up.longitude,
);
}
}
pub fn show_sector_element(&self, element: &SectorElement<'_>, component: &str, show: bool) {
let component = cstr_lossy(component);
unsafe {
euroscope_sys::es_screen_show_sector_element(
self.raw,
element.as_ptr(),
component.as_ptr(),
show,
);
}
}
#[expect(clippy::too_many_arguments)]
pub fn start_tag_function(
&self,
callsign: &str,
item_plugin: &str,
item_code: i32,
item_string: &str,
function_plugin: &str,
function_id: i32,
point: Point,
area: Rect,
) {
let callsign = cstr_lossy(callsign);
let item_plugin = cstr_lossy(item_plugin);
let item_string = cstr_lossy(item_string);
let function_plugin = cstr_lossy(function_plugin);
unsafe {
euroscope_sys::es_screen_start_tag_function(
self.raw,
callsign.as_ptr(),
item_plugin.as_ptr(),
item_code,
item_string.as_ptr(),
function_plugin.as_ptr(),
function_id,
point.x,
point.y,
area.left,
area.top,
area.right,
area.bottom,
);
}
}
}