#![allow(clippy::too_many_arguments)]
use std::convert::{TryFrom, TryInto};
use ncursesw::{ChtypeChar, ComplexChar, ComplexString};
use crate::{
BoxDrawingType, BoxDrawingGraphic, HorizontalGraphic, VerticalGraphic,
Origin, Size, NCurseswWinError,
gen::{
HasYXAxis, HasMvAddFunctions, HasMvInFunctions, HasMvInsFunctions,
GraphicsTransform, _Direction
}
};
pub trait HasGraphicFunctions: HasYXAxis + HasMvAddFunctions + HasMvInFunctions + HasMvInsFunctions + GraphicsTransform {
fn border(
&self,
ls: ChtypeChar,
rs: ChtypeChar,
ts: ChtypeChar,
bs: ChtypeChar,
tl: ChtypeChar,
tr: ChtypeChar,
bl: ChtypeChar,
br: ChtypeChar) -> result!(())
{
Ok(ncursesw::wborder(self._handle(), ls, rs, ts, bs, tl, tr, bl, br)?)
}
fn border_set(
&self,
ls: ComplexChar,
rs: ComplexChar,
ts: ComplexChar,
bs: ComplexChar,
tl: ComplexChar,
tr: ComplexChar,
bl: ComplexChar,
br: ComplexChar) -> result!(())
{
Ok(ncursesw::wborder_set(self._handle(), ls, rs, ts, bs, tl, tr, bl, br)?)
}
fn r#box(&self, verch: ChtypeChar, horch: ChtypeChar) -> result!(()) {
Ok(ncursesw::r#box(self._handle(), verch, horch)?)
}
fn box_set(&self, verch: ComplexChar, horch: ComplexChar) -> result!(()) {
Ok(ncursesw::box_set(self._handle(), verch, horch)?)
}
fn hline(&self, ch: ChtypeChar, length: u16) -> result!(()) {
Ok(ncursesw::whline(self._handle(), ch, i32::try_from(length)?)?)
}
fn hline_set(&self, wch: ComplexChar, length: u16) -> result!(()) {
Ok(ncursesw::whline_set(self._handle(), wch, i32::try_from(length)?)?)
}
fn mvhline(&self, origin: Origin, ch: ChtypeChar, length: u16) -> result!(()) {
assert_origin_hlength!("mvhline", self.size()?, origin, length);
Ok(ncursesw::mvwhline(self._handle(), origin.try_into()?, ch, i32::try_from(length)?)?)
}
fn mvhline_set(&self, origin: Origin, wch: ComplexChar, length: u16) -> result!(()) {
assert_origin_hlength!("mvhline_set", self.size()?, origin, length);
Ok(ncursesw::mvwhline_set(self._handle(), origin.try_into()?, wch, i32::try_from(length)?)?)
}
fn mvvline(&self, origin: Origin, ch: ChtypeChar, length: u16) -> result!(()) {
assert_origin_vlength!("mvvline", self.size()?, origin, length);
Ok(ncursesw::mvwvline(self._handle(), origin.try_into()?, ch, i32::try_from(length)?)?)
}
fn mvvline_set(&self, origin: Origin, wch: ComplexChar, length: u16) -> result!(()) {
assert_origin_vlength!("mvvline_set", self.size()?, origin, length);
Ok(ncursesw::mvwvline_set(self._handle(), origin.try_into()?, wch, i32::try_from(length)?)?)
}
fn vline(&self, ch: ChtypeChar, length: u16) -> result!(()) {
Ok(ncursesw::wvline(self._handle(), ch, i32::try_from(length)?)?)
}
fn vline_set(&self, wch: ComplexChar, length: u16) -> result!(()) {
Ok(ncursesw::wvline_set(self._handle(), wch, i32::try_from(length)?)?)
}
fn thline_set(
&self,
box_drawing_type: BoxDrawingType,
graphic: HorizontalGraphic,
length: u16
) -> result!(()) {
self.mvthline_set(self.cursor()?, box_drawing_type, graphic, length)
}
fn mvthline_set(
&self,
origin: Origin,
box_drawing_type: BoxDrawingType,
graphic: HorizontalGraphic,
length: u16
) -> result!(()) {
let window_size = self.size()?;
assert_origin_hlength!("mvthline_set", window_size, origin, length);
let complex_chars: Vec<ComplexChar> = ComplexString::into(self.mvin_wchnstr(origin, length)?);
let mut line_origin = origin;
let box_drawing_graphic = match graphic {
HorizontalGraphic::Upper => BoxDrawingGraphic::UpperHorizontalLine,
HorizontalGraphic::Center => BoxDrawingGraphic::HorizontalLine,
HorizontalGraphic::Lower => BoxDrawingGraphic::LowerHorizontalLine
};
for &complex_char in &complex_chars {
let graphic_char = self._transform_graphic(
complex_char,
box_drawing_type,
box_drawing_graphic,
line_origin,
Some(_Direction::Horizontal)
)?;
self._put_complex_char(line_origin, complex_char, graphic_char)?;
line_origin.x += 1;
if line_origin.x >= window_size.columns {
break;
}
}
Ok(())
}
fn tvline_set(
&self,
box_drawing_type: BoxDrawingType,
graphic: VerticalGraphic,
length: u16
) -> result!(()) {
self.mvtvline_set(self.cursor()?, box_drawing_type, graphic, length)
}
fn mvtvline_set(
&self,
origin: Origin,
box_drawing_type: BoxDrawingType,
graphic: VerticalGraphic,
length: u16
) -> result!(()) {
let window_size = self.size()?;
assert_origin_vlength!("mvtvline_set", window_size, origin, length);
let mut complex_chars = vec!();
let mut line_origin = origin;
for _ in 0..length {
complex_chars.push(self.mvin_wch(line_origin)?);
line_origin.y += 1;
}
line_origin = origin;
let box_drawing_graphic = match graphic {
VerticalGraphic::Left => BoxDrawingGraphic::LeftVerticalLine,
VerticalGraphic::Center => BoxDrawingGraphic::VerticalLine,
VerticalGraphic::Right => BoxDrawingGraphic::RightVerticalLine
};
for &complex_char in &complex_chars {
let graphic_char = self._transform_graphic(
complex_char,
box_drawing_type,
box_drawing_graphic,
line_origin,
Some(_Direction::Vertical)
)?;
self._put_complex_char(line_origin, complex_char, graphic_char)?;
line_origin.y += 1;
if line_origin.y >= window_size.lines {
break;
}
}
Ok(())
}
fn tbox_set(
&self,
size: Size,
box_drawing_type: BoxDrawingType
) -> result!(()) {
self.mvtbox_set(self.cursor()?, size, box_drawing_type)
}
fn mvtbox_set(
&self,
origin: Origin,
size: Size,
box_drawing_type: BoxDrawingType
) -> result!(()) {
let _window_size = self.size()?;
assert_origin!("mvtbox_set", _window_size, origin);
assert!(size.lines >= 2 && size.columns >= 2, "mvtbox_set() : size is invalid, size={}", size);
assert!(
origin.y + size.lines <= _window_size.lines,
"mvtbox_set() : attempting to write over window edge, origin.y={} + size.lines={} <= window_size.lines={}", origin.y, size.lines, _window_size.lines
);
assert!(
origin.x + size.columns <= _window_size.columns,
"mvtbox_set() : attempting to write over window edge, origin.x={} + size.columns={} <= window_size.columns={}", origin.x, size.columns, _window_size.columns
);
let set_corner_char = |corner_origin: Origin, box_drawing_graphic: BoxDrawingGraphic| -> result!(()) {
let graphic_char = self._transform_graphic(
self.mvin_wch(corner_origin)?,
box_drawing_type,
box_drawing_graphic,
corner_origin,
None
)?;
self._put_complex_char(corner_origin, self.mvin_wch(corner_origin)?, graphic_char)
};
set_corner_char(origin, BoxDrawingGraphic::UpperLeftCorner)?;
set_corner_char(Origin { y: origin.y, x: origin.x + (size.columns - 1) }, BoxDrawingGraphic::UpperRightCorner)?;
set_corner_char(Origin { y: origin.y + (size.lines - 1), x: origin.x }, BoxDrawingGraphic::LowerLeftCorner)?;
set_corner_char(Origin { y: origin.y + (size.lines - 1), x: origin.x + (size.columns - 1) }, BoxDrawingGraphic::LowerRightCorner)?;
if size.columns > 2 {
self.mvthline_set(Origin { y: origin.y, x: origin.x + 1}, box_drawing_type, HorizontalGraphic::Upper, size.columns - 2)?;
self.mvthline_set(Origin { y: origin.y + (size.lines - 1), x: origin.x + 1}, box_drawing_type, HorizontalGraphic::Lower, size.columns - 2)?;
}
if size.lines > 2 {
self.mvtvline_set(Origin { y: origin.y + 1, x: origin.x }, box_drawing_type, VerticalGraphic::Left, size.lines - 2)?;
self.mvtvline_set(Origin { y: origin.y + 1, x: origin.x + (size.columns - 1)}, box_drawing_type, VerticalGraphic::Right, size.lines - 2)?;
}
Ok(())
}
}