#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
use crate::ported::columnspanel::ColumnsPanel_update;
use crate::ported::crt::{KEY_ENTER, KEY_F, KEY_RECLICK};
use crate::ported::dynamiccolumn::{DynamicColumn, DynamicColumn_name};
use crate::ported::functionbar::FunctionBar_new;
use crate::ported::hashtable::{Hashtable, Hashtable_foreach};
use crate::ported::linux::linuxprocess::{Process_fields, LAST_PROCESSFIELD};
use crate::ported::listitem::{ListItem, ListItem_new};
use crate::ported::panel::{
HandlerResult, Panel, PanelClass, Panel_add, Panel_done, Panel_getSelected,
Panel_getSelectedIndex, Panel_insert, Panel_new, Panel_prune, Panel_selectByTyping,
Panel_setHeader, Panel_setSelected,
};
#[cfg(target_os = "macos")]
use crate::ported::darwin::platform::Platform_addDynamicScreenAvailableColumns;
#[cfg(target_os = "dragonfly")]
use crate::ported::dragonflybsd::platform::Platform_addDynamicScreenAvailableColumns;
#[cfg(target_os = "freebsd")]
use crate::ported::freebsd::platform::Platform_addDynamicScreenAvailableColumns;
#[cfg(target_os = "linux")]
use crate::ported::linux::platform::Platform_addDynamicScreenAvailableColumns;
#[cfg(target_os = "netbsd")]
use crate::ported::netbsd::platform::Platform_addDynamicScreenAvailableColumns;
#[cfg(target_os = "openbsd")]
use crate::ported::openbsd::platform::Platform_addDynamicScreenAvailableColumns;
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
use crate::ported::solaris::platform::Platform_addDynamicScreenAvailableColumns;
#[cfg(not(any(
target_os = "macos",
target_os = "linux",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "solaris",
target_os = "illumos",
target_os = "dragonfly"
)))]
use crate::ported::unsupported::platform::Platform_addDynamicScreenAvailableColumns;
const ROW_DYNAMIC_FIELDS: i32 = LAST_PROCESSFIELD as i32;
static AvailableColumnsFunctions: [&str; 10] = [
" ", " ", " ", " ", "Add ", " ", " ", " ", " ",
"Done ",
];
pub struct AvailableColumnsPanel {
pub super_: Panel,
pub columns: *mut Panel,
}
impl PanelClass for AvailableColumnsPanel {
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 {
AvailableColumnsPanel_eventHandler(self, ev)
}
}
pub fn AvailableColumnsPanel_delete(this: AvailableColumnsPanel) {
let AvailableColumnsPanel { super_, columns } = this;
Panel_done(super_);
let _ = columns;
}
pub fn AvailableColumnsPanel_insert(this: &mut AvailableColumnsPanel, at: i32, key: i32) {
let name: &str = if key >= ROW_DYNAMIC_FIELDS {
DynamicColumn_name(key as u32)
.expect("AvailableColumnsPanel_insert: DynamicColumn_name returned None")
} else {
Process_fields[key as usize].name
};
let columns = unsafe { &mut *this.columns };
Panel_insert(columns, at, Box::new(ListItem_new(name, key)));
}
pub fn AvailableColumnsPanel_eventHandler(
this: &mut AvailableColumnsPanel,
ch: i32,
) -> HandlerResult {
const KEY_F5: i32 = KEY_F(5);
let mut result = HandlerResult::IGNORED;
match ch {
13 | KEY_ENTER | KEY_RECLICK | KEY_F5 => {
let key = match Panel_getSelected(&this.super_) {
None => return result,
Some(obj) => {
let any: &dyn core::any::Any = obj;
any.downcast_ref::<ListItem>()
.expect("AvailableColumnsPanel_eventHandler: selected is not a ListItem")
.key
}
};
let at = Panel_getSelectedIndex(unsafe { &*this.columns });
AvailableColumnsPanel_insert(this, at, key);
Panel_setSelected(unsafe { &mut *this.columns }, at + 1);
ColumnsPanel_update(unsafe { &mut *this.columns });
result = HandlerResult::HANDLED;
}
_ => {
if 0 < ch && ch < 255 && (ch as u8).is_ascii_graphic() {
result = Panel_selectByTyping(&mut this.super_, ch);
}
}
}
result
}
pub fn AvailableColumnsPanel_addDynamicColumn(
key: u32,
column: &DynamicColumn,
this: &mut AvailableColumnsPanel,
) {
if !column.table.is_null() {
return;
}
let title: &str = column.heading.as_deref().unwrap_or(&column.name);
let text: Option<&str> = column.description.as_deref().or(column.caption.as_deref());
let description = match text {
Some(text) => format!("{title} - {text}"),
None => title.to_string(),
};
Panel_add(
&mut this.super_,
Box::new(ListItem_new(&description, key as i32)),
);
}
pub fn AvailableColumnsPanel_addDynamicColumns(
this: &mut AvailableColumnsPanel,
dynamicColumns: &Hashtable,
) {
Hashtable_foreach(dynamicColumns, &mut |key, value| {
let any: &dyn core::any::Any = value;
let column = any.downcast_ref::<DynamicColumn>().expect(
"AvailableColumnsPanel_addDynamicColumns: hashtable value is not a DynamicColumn",
);
AvailableColumnsPanel_addDynamicColumn(key, column, this);
});
}
pub fn AvailableColumnsPanel_addPlatformColumns(this: &mut AvailableColumnsPanel) {
for i in 1..LAST_PROCESSFIELD {
if let Some(desc) = Process_fields[i].description {
let description = format!("{} - {}", Process_fields[i].name, desc);
Panel_add(
&mut this.super_,
Box::new(ListItem_new(&description, i as i32)),
);
}
}
}
pub fn AvailableColumnsPanel_addDynamicScreens(this: &mut AvailableColumnsPanel, screen: &str) {
Platform_addDynamicScreenAvailableColumns(&mut this.super_, screen);
}
pub fn AvailableColumnsPanel_fill(
this: &mut AvailableColumnsPanel,
dynamicScreen: Option<&str>,
dynamicColumns: Option<&Hashtable>,
) {
Panel_prune(&mut this.super_);
if let Some(screen) = dynamicScreen {
AvailableColumnsPanel_addDynamicScreens(this, screen);
} else {
AvailableColumnsPanel_addPlatformColumns(this);
AvailableColumnsPanel_addDynamicColumns(
this,
dynamicColumns.expect(
"AvailableColumnsPanel_fill: dynamicColumns is NULL in the non-screen branch",
),
);
}
}
pub fn AvailableColumnsPanel_new(
columns: *mut Panel,
dynamicColumns: &Hashtable,
) -> AvailableColumnsPanel {
let fuBar = FunctionBar_new(Some(&AvailableColumnsFunctions[..]), None, None);
let super_ = Panel_new(1, 1, 1, 1, Some(fuBar));
let mut this = AvailableColumnsPanel { super_, columns };
Panel_setHeader(&mut this.super_, "Available Columns");
AvailableColumnsPanel_fill(&mut this, None, Some(dynamicColumns));
this
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ported::listitem::ListItem;
use crate::ported::panel::{Panel_new, Panel_size};
use crate::ported::table::Table;
fn panel() -> AvailableColumnsPanel {
AvailableColumnsPanel {
super_: Panel_new(0, 0, 1, 1, None),
columns: core::ptr::null_mut(),
}
}
fn column(
name: &str,
heading: Option<&str>,
description: Option<&str>,
caption: Option<&str>,
table: *const Table,
) -> DynamicColumn {
DynamicColumn {
name: name.to_string(),
heading: heading.map(str::to_string),
caption: caption.map(str::to_string),
description: description.map(str::to_string),
width: 0,
enabled: true,
table,
}
}
fn item_at(this: &AvailableColumnsPanel, i: usize) -> (&str, i32) {
let obj: &dyn core::any::Any = this.super_.items[i].object();
let li = obj
.downcast_ref::<ListItem>()
.expect("panel item is not a ListItem");
(li.value.as_str(), li.key)
}
#[test]
fn addDynamicColumn_uses_heading_and_description() {
let mut p = panel();
let col = column(
"io_rate",
Some("IO"),
Some("disk io rate"),
None,
core::ptr::null(),
);
AvailableColumnsPanel_addDynamicColumn(7, &col, &mut p);
assert_eq!(Panel_size(&p.super_), 1);
assert_eq!(item_at(&p, 0), ("IO - disk io rate", 7));
}
#[test]
fn addDynamicColumn_falls_back_to_name_and_caption() {
let mut p = panel();
let col = column("io_rate", None, None, Some("io"), core::ptr::null());
AvailableColumnsPanel_addDynamicColumn(3, &col, &mut p);
assert_eq!(item_at(&p, 0), ("io_rate - io", 3));
}
#[test]
fn addDynamicColumn_no_text_uses_title_only() {
let mut p = panel();
let col = column("io_rate", Some("IO"), None, None, core::ptr::null());
AvailableColumnsPanel_addDynamicColumn(1, &col, &mut p);
assert_eq!(item_at(&p, 0), ("IO", 1));
}
#[test]
fn addDynamicColumn_skips_dynamicscreen_columns() {
let mut p = panel();
let table = core::ptr::NonNull::<Table>::dangling().as_ptr() as *const Table;
let col = column("io_rate", Some("IO"), Some("desc"), None, table);
AvailableColumnsPanel_addDynamicColumn(9, &col, &mut p);
assert_eq!(Panel_size(&p.super_), 0);
}
#[test]
fn addDynamicColumns_adds_every_non_screen_column() {
use crate::ported::hashtable::{Hashtable_new, Hashtable_put};
let mut ht = Hashtable_new(0, true);
Hashtable_put(
&mut ht,
5,
Box::new(column(
"cpu",
Some("CPU"),
Some("cpu usage"),
None,
core::ptr::null(),
)),
);
let mut p = panel();
AvailableColumnsPanel_addDynamicColumns(&mut p, &ht);
assert_eq!(Panel_size(&p.super_), 1);
assert_eq!(item_at(&p, 0), ("CPU - cpu usage", 5));
}
}