#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
use core::any::Any;
use crate::ported::crt::{KEY_ENTER, KEY_MOUSE, KEY_RECLICK};
use crate::ported::functionbar::FunctionBar_new;
use crate::ported::header::Header_setLayout;
use crate::ported::optionitem::{CheckItem, CheckItem_newByVal, CheckItem_set};
use crate::ported::panel::{
HandlerResult, Panel, PanelClass, Panel_add, Panel_done, Panel_getSelectedIndex, Panel_new,
Panel_setHeader,
};
use crate::ported::screenmanager::{ScreenManager, ScreenManager_resize};
use crate::ported::settings::{HeaderLayout, HeaderLayout_layouts, Settings};
static HeaderOptionsFunctions: [&str; 10] = [
" ", " ", " ", " ", " ", " ", " ", " ", " ",
"Done ",
];
pub struct HeaderOptionsPanel {
pub super_: Panel,
pub scr: *mut ScreenManager,
pub settings: *mut Settings,
}
impl PanelClass for HeaderOptionsPanel {
fn as_panel(&self) -> &Panel {
&self.super_
}
fn as_panel_mut(&mut self) -> &mut Panel {
&mut self.super_
}
fn event_handler(&mut self, ev: i32) -> HandlerResult {
HeaderOptionsPanel_eventHandler(self, ev)
}
}
pub fn HeaderOptionsPanel_delete(this: HeaderOptionsPanel) {
let HeaderOptionsPanel {
super_,
scr,
settings,
} = this;
Panel_done(super_);
let _ = scr;
let _ = settings;
}
pub fn HeaderOptionsPanel_eventHandler(this: &mut HeaderOptionsPanel, ch: i32) -> HandlerResult {
let mut result = HandlerResult::IGNORED;
match ch {
0x0a | 0x0d | KEY_ENTER | KEY_MOUSE | KEY_RECLICK | 0x20 => {
let mark = Panel_getSelectedIndex(&this.super_);
debug_assert!(mark >= 0);
debug_assert!((mark as usize) < HeaderLayout::LAST_HEADER_LAYOUT as usize);
for i in 0..(HeaderLayout::LAST_HEADER_LAYOUT as usize) {
let any: &mut dyn Any = this.super_.items[i].object_mut();
if let Some(item) = any.downcast_mut::<CheckItem>() {
CheckItem_set(item, false);
}
}
let any: &mut dyn Any = this.super_.items[mark as usize].object_mut();
if let Some(item) = any.downcast_mut::<CheckItem>() {
CheckItem_set(item, true);
}
let layout = match mark {
0 => HeaderLayout::HF_ONE_100,
1 => HeaderLayout::HF_TWO_50_50,
2 => HeaderLayout::HF_TWO_33_67,
3 => HeaderLayout::HF_TWO_67_33,
4 => HeaderLayout::HF_THREE_33_34_33,
5 => HeaderLayout::HF_THREE_25_25_50,
6 => HeaderLayout::HF_THREE_25_50_25,
7 => HeaderLayout::HF_THREE_50_25_25,
8 => HeaderLayout::HF_THREE_40_30_30,
9 => HeaderLayout::HF_THREE_30_40_30,
10 => HeaderLayout::HF_THREE_30_30_40,
11 => HeaderLayout::HF_THREE_40_20_40,
12 => HeaderLayout::HF_FOUR_25_25_25_25,
_ => unreachable!("mark out of [0, LAST_HEADER_LAYOUT) range"),
};
let scr = unsafe { &mut *this.scr };
let header = unsafe { scr.header.as_mut() }
.expect("HeaderOptionsPanel_eventHandler: scr->header is NULL");
Header_setLayout(header, layout);
let settings = unsafe { &mut *this.settings };
settings.changed = true;
settings.lastUpdate += 1;
ScreenManager_resize(scr);
result = HandlerResult::HANDLED;
}
_ => {}
}
result
}
pub fn HeaderOptionsPanel_new(
settings: *mut Settings,
scr: *mut ScreenManager,
) -> HeaderOptionsPanel {
let fuBar = FunctionBar_new(Some(&HeaderOptionsFunctions[..]), None, None);
let super_ = Panel_new(1, 1, 1, 1, Some(fuBar));
let mut this = HeaderOptionsPanel {
super_,
scr,
settings,
};
Panel_setHeader(&mut this.super_, "Header Layout");
for i in 0..(HeaderLayout::LAST_HEADER_LAYOUT as usize) {
Panel_add(
&mut this.super_,
Box::new(CheckItem_newByVal(
HeaderLayout_layouts[i].description,
false,
)),
);
}
let headerLayout = unsafe { (*scr).header.as_ref() }
.expect("HeaderOptionsPanel_new: scr->header is NULL")
.headerLayout as usize;
let any: &mut dyn Any = this.super_.items[headerLayout].object_mut();
if let Some(item) = any.downcast_mut::<CheckItem>() {
CheckItem_set(item, true);
}
this
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ported::action::State;
use crate::ported::machine::Machine;
use crate::ported::optionitem::{CheckItem_get, CheckItem_newByVal};
use crate::ported::panel::{Panel_add, Panel_new, Panel_setSelected};
use crate::ported::screenmanager::ScreenManager_new;
fn state() -> State {
State {
pauseUpdate: false,
hideSelection: false,
hideMeters: false,
host: core::ptr::null_mut(),
mainPanel: core::ptr::null_mut(),
header: core::ptr::null_mut(),
failedUpdate: None,
}
}
fn settings() -> Settings {
Settings {
hLayout: HeaderLayout::HF_ONE_100,
hColumns: Vec::new(),
screens: Vec::new(),
ssIndex: 0,
changed: false,
lastUpdate: 0,
..Default::default()
}
}
fn header() -> crate::ported::header::Header {
crate::ported::header::Header {
host: core::ptr::null(),
columns: vec![Vec::new()],
headerLayout: HeaderLayout::HF_ONE_100,
pad: 0,
height: 0,
headerMargin: false,
screenTabs: false,
}
}
fn options_panel() -> Panel {
let mut p = Panel_new(1, 1, 20, 10, None);
for _ in 0..(HeaderLayout::LAST_HEADER_LAYOUT as usize) {
Panel_add(&mut p, Box::new(CheckItem_newByVal("row", false)));
}
p
}
fn item_checked(p: &Panel, i: usize) -> bool {
let any: &dyn Any = p.items[i].object();
CheckItem_get(any.downcast_ref::<CheckItem>().unwrap())
}
#[test]
fn enter_applies_selected_layout_and_marks_only_that_row() {
let mut scr = ScreenManager_new(Some(header()), Machine::default(), state());
scr.panelCount = 1;
scr.panels.push(Box::new(Panel_new(0, 0, 10, 5, None)));
let mut set = settings();
let mut this = HeaderOptionsPanel {
super_: options_panel(),
scr: &mut scr as *mut ScreenManager,
settings: &mut set as *mut Settings,
};
Panel_setSelected(&mut this.super_, 2);
let r = HeaderOptionsPanel_eventHandler(&mut this, ' ' as i32);
assert_eq!(r, HandlerResult::HANDLED);
for i in 0..(HeaderLayout::LAST_HEADER_LAYOUT as usize) {
assert_eq!(item_checked(&this.super_, i), i == 2, "row {i} check state");
}
assert_eq!(
scr.header.as_ref().unwrap().headerLayout,
HeaderLayout::HF_TWO_33_67
);
assert!(set.changed);
assert_eq!(set.lastUpdate, 1);
}
#[test]
fn non_activation_key_is_ignored() {
let mut scr = ScreenManager_new(Some(header()), Machine::default(), state());
scr.panelCount = 1;
scr.panels.push(Box::new(Panel_new(0, 0, 10, 5, None)));
let mut set = settings();
let mut this = HeaderOptionsPanel {
super_: options_panel(),
scr: &mut scr as *mut ScreenManager,
settings: &mut set as *mut Settings,
};
Panel_setSelected(&mut this.super_, 2);
let r = HeaderOptionsPanel_eventHandler(&mut this, 'x' as i32);
assert_eq!(r, HandlerResult::IGNORED);
for i in 0..(HeaderLayout::LAST_HEADER_LAYOUT as usize) {
assert!(!item_checked(&this.super_, i));
}
assert!(!set.changed);
assert_eq!(set.lastUpdate, 0);
assert_eq!(
scr.header.as_ref().unwrap().headerLayout,
HeaderLayout::HF_ONE_100
);
}
}