use std::fmt;
use super::canvas;
use crate::chart::plotchart;
use super::font;
use super::image;
use super::wish;
#[derive(Clone, Debug)]
pub struct TkEvent {
pub x: i64,
pub y: i64,
pub root_x: i64,
pub root_y: i64,
pub height: i64,
pub width: i64,
pub key_code: u64,
pub key_symbol: String,
pub mouse_button: u64,
}
pub trait TkWidget {
fn id(&self) -> &str;
fn bind(&self, pattern: &str, command: impl Fn(TkEvent) + Send + 'static) {
bind_to(&self.id(), pattern, command);
}
fn cget(&self, option: &str) -> String {
let msg = format!("puts [{} cget -{}] ; flush stdout", self.id(), option);
wish::ask_wish(&msg)
}
fn configure(&self, option: &str, value: &str) {
configure(&self.id(), option, value);
}
fn destroy(&self) {
let msg = format!("destroy {}", self.id());
wish::tell_wish(&msg);
}
fn winfo(&self, option: &str) -> String {
let msg = format!("winfo {} {}", option, self.id());
wish::ask_wish(&msg)
}
fn focus(&self) {
let msg = format!("focus {}", self.id());
wish::tell_wish(&msg);
}
fn position_x(&self) -> u64 {
let msg = format!("winfo x {}", self.id());
let result = wish::ask_wish(&msg);
if let Ok(value) = result.parse::<u64>() {
value
} else {
0
}
}
fn position_y(&self) -> u64 {
let msg = format!("winfo y {}", self.id());
let result = wish::ask_wish(&msg);
if let Ok(value) = result.parse::<u64>() {
value
} else {
0
}
}
fn widget_height(&self) -> u64 {
let msg = format!("winfo height {}", self.id());
let result = wish::ask_wish(&msg);
if let Ok(value) = result.parse::<u64>() {
value
} else {
0
}
}
fn widget_width(&self) -> u64 {
let msg = format!("winfo width {}", self.id());
let result = wish::ask_wish(&msg);
if let Ok(value) = result.parse::<u64>() {
value
} else {
0
}
}
fn mouse_position(&self) -> (i64, i64) {
(self.mouse_x(), self.mouse_y())
}
fn mouse_x(&self) -> i64 {
let msg = format!("winfo pointerx {}", self.id());
let result = wish::ask_wish(&msg);
if let Ok(value) = result.parse::<i64>() {
value
} else {
-1
}
}
fn mouse_y(&self) -> i64 {
let msg = format!("winfo pointery {}", self.id());
let result = wish::ask_wish(&msg);
if let Ok(value) = result.parse::<i64>() {
value
} else {
-1
}
}
fn screen_height(&self) -> u64 {
let msg = format!("winfo screenheight {}", self.id());
let result = wish::ask_wish(&msg);
if let Ok(value) = result.parse::<u64>() {
value
} else {
0
}
}
fn screen_height_mm(&self) -> u64 {
let msg = format!("winfo screenmmheight {}", self.id());
let result = wish::ask_wish(&msg);
if let Ok(value) = result.parse::<u64>() {
value
} else {
0
}
}
fn screen_width(&self) -> u64 {
let msg = format!("winfo screenwidth {}", self.id());
let result = wish::ask_wish(&msg);
if let Ok(value) = result.parse::<u64>() {
value
} else {
0
}
}
fn screen_width_mm(&self) -> u64 {
let msg = format!("winfo screenmmwidth {}", self.id());
let result = wish::ask_wish(&msg);
if let Ok(value) = result.parse::<u64>() {
value
} else {
0
}
}
fn lower(&self) {
let msg = format!("lower {}", self.id());
wish::tell_wish(&msg);
}
fn raise(&self) {
let msg = format!("raise {}", self.id());
wish::tell_wish(&msg);
}
fn grid_configure_column(&self, index: u64, option: &str, value: &str) {
let msg = format!(
"grid columnconfigure {} {} -{} {{{}}}",
self.id(),
index,
option,
value
);
wish::tell_wish(&msg);
}
fn grid_configure_row(&self, index: u64, option: &str, value: &str) {
let msg = format!(
"grid rowconfigure {} {} -{} {{{}}}",
self.id(),
index,
option,
value
);
wish::tell_wish(&msg);
}
}
pub trait TkLabelOptions: TkWidget {
fn compound(&self, value: Compound) {
configure(&self.id(), "compound", &value.to_string());
}
fn font(&self, definition: &font::TkFont) {
configure(&self.id(), "font", &definition.to_string());
}
fn foreground(&self, colour: &str) {
configure(&self.id(), "foreground", colour);
}
fn image(&self, image: &image::TkImage) {
configure(&self.id(), "image", &image.id);
}
fn padding(&self, values: &[u64]) {
padding(&self.id(), values);
}
fn text(&self, value: &str) {
configure(&self.id(), "text", value);
}
fn underline(&self, index: u64) {
configure(&self.id(), "underline", &index.to_string());
}
fn width(&self, value: i64) {
let msg = format!("{} configure -width {{{}}}", self.id(), value);
wish::tell_wish(&msg);
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Anchor {
N,
NE,
E,
SE,
S,
SW,
W,
NW,
Center,
Centre,
}
impl fmt::Display for Anchor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
Anchor::N => "n",
Anchor::NE => "ne",
Anchor::E => "e",
Anchor::SE => "se",
Anchor::S => "s",
Anchor::SW => "sw",
Anchor::W => "w",
Anchor::NW => "nw",
Anchor::Center | Anchor::Centre => "center",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Compound {
Bottom,
Center,
Centre,
Image,
Left,
None,
Right,
Text,
Top,
}
impl fmt::Display for Compound {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
Compound::Bottom => "bottom",
Compound::Center | Compound::Centre => "center",
Compound::Image => "image",
Compound::Left => "left",
Compound::None => "none",
Compound::Right => "right",
Compound::Text => "text",
Compound::Top => "top",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum DialogType {
AbortRetryIgnore,
Ok,
OkCancel,
RetryCancel,
YesNo,
YesNoCancel,
}
impl fmt::Display for DialogType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
DialogType::AbortRetryIgnore => "abortretryignore",
DialogType::Ok => "ok",
DialogType::OkCancel => "okcancel",
DialogType::RetryCancel => "retrycancel",
DialogType::YesNo => "yesno",
DialogType::YesNoCancel => "yesnocancel",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum IconImage {
Error,
Information,
Question,
Warning,
}
impl fmt::Display for IconImage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
IconImage::Error => "error",
IconImage::Information => "info",
IconImage::Question => "question",
IconImage::Warning => "warning",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Justify {
Center,
Centre,
Left,
Right,
}
impl fmt::Display for Justify {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
Justify::Left => "left",
Justify::Center | Justify::Centre => "center",
Justify::Right => "right",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Orientation {
Horizontal,
Vertical,
}
impl fmt::Display for Orientation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
Orientation::Horizontal => "horizontal",
Orientation::Vertical => "vertical",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum PackFill {
Both,
None,
X,
Y
}
impl fmt::Display for PackFill {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
PackFill::Both => "both",
PackFill::None => "none",
PackFill::X => "x",
PackFill::Y => "y",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum PackSide {
Bottom,
Left,
Right,
Top,
}
impl fmt::Display for PackSide {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
PackSide::Bottom => "bottom",
PackSide::Left => "left",
PackSide::Right => "right",
PackSide::Top => "top",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum ProgressMode {
Determinate,
Indeterminate,
}
impl fmt::Display for ProgressMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
ProgressMode::Determinate => "determinate",
ProgressMode::Indeterminate => "indeterminate",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Relief {
Flat,
Groove,
Raised,
Ridge,
Solid,
Sunken,
}
impl fmt::Display for Relief {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
Relief::Flat => "flat",
Relief::Groove => "groove",
Relief::Raised => "raised",
Relief::Ridge => "ridge",
Relief::Solid => "solid",
Relief::Sunken => "sunken",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Selection {
Multiple,
Single,
None,
}
impl fmt::Display for Selection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
Selection::Multiple => "extended",
Selection::None => "none",
Selection::Single => "browse",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Sticky {
N,
NE,
NES,
NEW,
NESW,
NS,
NSW,
NW,
E,
ES,
ESW,
EW,
S,
SW,
W,
None,
}
impl fmt::Display for Sticky {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
Sticky::N => "n",
Sticky::NE => "ne",
Sticky::NES => "nes",
Sticky::NEW => "new",
Sticky::NESW => "nesw",
Sticky::NS => "ns",
Sticky::NSW => "nsw",
Sticky::NW => "nw",
Sticky::E => "e",
Sticky::ES => "es",
Sticky::EW => "ew",
Sticky::ESW => "esw",
Sticky::S => "s",
Sticky::SW => "sw",
Sticky::W => "w",
Sticky::None => "",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum State {
Active,
Disabled,
Normal,
Readonly,
}
impl fmt::Display for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
State::Active => "active",
State::Disabled => "disabled",
State::Normal => "normal",
State::Readonly => "readonly",
};
write!(f, "{}", &value)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Wrapping {
Char,
None,
Word,
}
impl fmt::Display for Wrapping {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = match self {
Wrapping::Char => "char",
Wrapping::None => "none",
Wrapping::Word => "word",
};
write!(f, "{}", &value)
}
}
pub(super) fn bind_to(tag: &str, pattern: &str, command: impl Fn(TkEvent) + Send + 'static) {
let tag_pattern = format!("{}{}", tag, pattern); wish::add_callback1_event(&tag_pattern, wish::mk_callback1_event(command));
let msg = format!(
"bind {} {} {{ puts cb1e:{}:%x:%y:%X:%Y:%h:%w:%k:%K:%b ; flush stdout }}",
tag, pattern, tag_pattern
);
wish::tell_wish(&msg);
}
pub(super) fn configure(wid: &str, option: &str, value: &str) {
let msg = format!("{} configure -{} {{{}}}", wid, option, value);
wish::tell_wish(&msg);
}
pub(super) fn padding(wid: &str, values: &[u64]) {
let mut value_str = String::new();
for i in values.iter() {
value_str.push_str(&i.to_string());
value_str.push(' ');
}
configure(wid, "padding", &value_str);
}
pub(super) fn strings_list(values: &[&str]) -> String {
let mut values_str = String::new();
for value in values {
values_str.push_str(&format!("{} ", value));
}
values_str
}
pub(super) fn str_list(values: &[f64]) -> String {
let mut values_str = String::new();
for value in values {
values_str.push_str(&format!("{} ", value));
}
values_str
}
pub(super) fn str_list_lists<M: AsRef<[R]>, R: AsRef<[f64]>>(values: M) -> String {
let mut values_str = String::new();
for vs in values.as_ref() {
values_str.push_str("{");
values_str.push_str(&str_list(vs.as_ref()));
values_str.push_str("} ");
}
values_str
}
pub fn after(time: u64, command: impl Fn() + Send + 'static) {
wish::next_wid(".");
let name = format!("after{}", wish::current_id());
wish::add_callback0(&name, wish::mk_callback0(command));
let msg = format!("after {} {{ puts clicked-{} ; flush stdout }}",
time, name);
wish::tell_wish(&msg);
}
pub fn bind(pattern: &str, command: impl Fn(TkEvent) + Send + 'static) {
bind_to("all", pattern, command);
}
pub fn colour_map(map: plotchart::ColourMap) {
let msg = format!("::Plotchart::colorMap {}", map);
wish::tell_wish(&msg);
}
pub fn plot_pack(canvas: &canvas::TkCanvas,
direction: plotchart::PlotDirection,
charts: &[&impl plotchart::TkPlotchart]) {
let mut charts_str = String::new();
for chart in charts {
charts_str.push_str(&format!("${} ", chart.id()));
}
let msg = format!("::Plotchart::plotpack {} {} {}",
&canvas.id, direction, charts_str);
wish::tell_wish(&msg);
}
pub fn windowing_system() -> String {
wish::ask_wish("tk windowingsystem")
}