use enumx::export::*;
use enumx::predefined::*;
use cex::*;
use crate::{
InterpResult,
OptPair,
PathOptsWidgets,
Tk,
TkInstance,
TkOption,
Widget,
cmd::append_opts,
opt::TkFontOpt,
};
use std::os::raw::{c_int, c_longlong};
use tcl::{
Obj,
error::{
NotList,
NotSeqOf,
InterpError,
},
};
use tuplex::*;
#[derive( Copy, Clone )]
pub enum Style {
Normal,
Bold,
Roman,
Italic,
Underline,
Overstrike,
}
impl From<Style> for Obj {
fn from( style: Style ) -> Obj {
match style {
Style::Normal => "normal" .into(),
Style::Bold => "bold" .into(),
Style::Roman => "roman" .into(),
Style::Italic => "italic" .into(),
Style::Underline => "underline" .into(),
Style::Overstrike => "overstrike" .into(),
}
}
}
pub enum Font<'a, Opts> {
Name( &'a str ),
System( &'a str ),
Family{ family: &'a str, size: Option<c_int>, styles: &'a [Style] },
XFont( &'a str ),
Opts( Opts ),
}
impl<'a, Opts> From<Font<'a, Opts>> for Obj
where Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
fn from( font: Font<'a, Opts> ) -> Obj {
match font {
Font::Name( name ) |
Font::System( name ) |
Font::XFont( name ) => name.into(),
Font::Family{ family, size, styles } => {
(family, size, styles.to_vec() ).into()
},
Font::Opts( opts ) => {
let mut v = Vec::new();
append_opts( &mut v, opts );
v.into()
},
}
}
}
impl<Inst:TkInstance> Tk<Inst> {
pub fn font_actual<'a, Opt, Opts>( &self, font: Font<'a, Opts>, _option: Opt, ch: Option<char> ) -> InterpResult<Obj>
where Opt : TkOption
+ Into<TkFontOpt>
, Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let font = Obj::from( font );
let option = Obj::from( <Opt as TkOption>::NAME );
match ch {
Some( '-' ) => self.eval(( "font", "actual", font, option, "--", "-" )),
Some( ch ) => self.eval(( "font", "actual", font, option, Obj::from(ch) )),
None => self.eval(( "font", "actual", font, option )),
}
}
pub fn font_actual_get_all<'a, Opts>( &self, font: Font<'a, Opts> ) -> InterpResult<Obj>
where Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let font = Obj::from( font );
self.eval(( "font", "actual", font ))
}
pub fn font_configure<Opts>( &self, fontname: &str, opts: impl Into<PathOptsWidgets<Opts,()>> ) -> InterpResult<()>
where Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let mut command = Vec::<Obj>::with_capacity( <<Opts as IntoHomoTuple<OptPair>>::Output as tuplex::Len>::LEN * 2 + 3 );
command.push( "font".into() );
command.push( "configure".into() );
command.push( fontname.into() );
append_opts( &mut command, opts.into().opts );
self.run( command )
}
pub fn font_configure_get<Opt>( &self, fontname: &str, _opt: Opt ) -> InterpResult<Obj>
where Opt : TkOption
+ Into<TkFontOpt>
{
self.eval(( "font", "configure", fontname, <Opt as TkOption>::NAME ))
}
#[cex]
pub fn font_configure_get_all( &self, fontname: &str ) -> Result!( Vec<OptPair>
throws InterpError, NotList, NotSeqOf<OptPair> )
{
let mut opt_pairs = Vec::new();
let obj = self.eval(( "font", "configure", fontname ))?;
let mut pairs = obj.clone().get_elements()?;
while let Some( name ) = pairs.next() {
let value = if let Some( value ) = pairs.next() {
value.clone()
} else {
throw!( NotSeqOf::new( obj.clone() ));
};
let name = match name.get_string().as_str() {
"-family" => "family" ,
"-size" => "size" ,
"-weight" => "weight" ,
"-slant" => "slant" ,
"-underline" => "underline" ,
"-overstrike" => "overstrike",
_ => throw!( NotSeqOf::new( obj )),
};
opt_pairs.push( OptPair{ name, value });
}
Ok( opt_pairs )
}
pub fn font_create<Opts>( &self, fontname: &str, opts: impl Into<PathOptsWidgets<Opts,()>> ) -> InterpResult<Obj>
where Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let mut command = Vec::<Obj>::with_capacity( <<Opts as IntoHomoTuple<OptPair>>::Output as tuplex::Len>::LEN * 2 + 3 );
command.push( "font".into() );
command.push( "create".into() );
command.push( fontname.into() );
append_opts( &mut command, opts.into().opts );
self.eval( command )
}
pub fn font_create_with_auto_name<Opts>( &self, opts: impl Into<PathOptsWidgets<Opts,()>> ) -> InterpResult<Obj>
where Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let mut command = Vec::<Obj>::with_capacity( <<Opts as IntoHomoTuple<OptPair>>::Output as tuplex::Len>::LEN * 2 + 2 );
command.push( "font".into() );
command.push( "create".into() );
append_opts( &mut command, opts.into().opts );
self.eval( command )
}
pub fn font_delete( &self, names: &[Obj] ) -> InterpResult<()> {
let mut command = Vec::<Obj>::with_capacity( names.len() + 2 );
command.push( "font".into() );
command.push( "delete".into() );
command.extend( names.iter().map( |name| name.clone() ));
self.run( command )
}
#[cex]
pub fn font_families( &self ) -> Result!( Vec<String> throws InterpError, NotList ) {
let list = self.eval(( "font", "families" ))?;
Ok( list.get_elements()?.map( |obj| obj.get_string() ).collect() )
}
pub fn font_measure<'a, Opts>( &self, font: Font<'a, Opts>, text: impl Into<String> ) -> InterpResult<c_longlong>
where Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let font = Obj::from( font );
self.longlong( self.eval(( "font", "measure", font, text.into() ))? )
}
pub fn font_metrics<'a, Opt, Opts>( &self, font: Font<'a, Opts>, _opt: Opt ) -> InterpResult<Obj>
where Opt : TkOption
+ Into<TkFontOpt>
, Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let font = Obj::from( font );
let option = Obj::from( <Opt as TkOption>::NAME );
self.eval(( "font", "metrics", font, option ))
}
#[cex]
pub fn font_metrics_get_all<'a, Opts>( &self, font: Font<'a, Opts> ) -> Result!( Vec<OptPair>
throws InterpError, NotList, NotSeqOf<OptPair> )
where Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let font = Obj::from( font );
let mut opt_pairs = Vec::new();
let obj = self.eval(( "font", "metrics", font ))?;
let mut pairs = obj.clone().get_elements()?;
while let Some( name ) = pairs.next() {
let value = if let Some( value ) = pairs.next() {
value.clone()
} else {
throw!( NotSeqOf::new( obj.clone() ));
};
let name = match name.get_string().as_str() {
"-ascent" => "ascent" ,
"-descent" => "descent" ,
"-linespace" => "linespace",
"-fixed" => "fixed" ,
_ => throw!( NotSeqOf::new( obj )),
};
opt_pairs.push( OptPair{ name, value });
}
Ok( opt_pairs )
}
#[cex]
pub fn font_names( &self ) -> Result!( Vec<String> throws InterpError, NotList ) {
let list = self.eval(( "font", "names" ))?;
Ok( list.get_elements()?.map( |obj| obj.get_string() ).collect() )
}
}
impl<Inst:TkInstance> Widget<Inst> {
pub fn font_actual<'a, Opt, Opts>( &self, font: Font<'a, Opts>, _option: Opt, ch: Option<char> ) -> InterpResult<Obj>
where Opt : TkOption
+ Into<TkFontOpt>
, Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let font = Obj::from( font );
let option = Obj::from( <Opt as TkOption>::NAME );
match ch {
Some( '-' ) => self.tk().eval(( "font", "actual", font, "-displayof", self.path, option, "--", "-" )),
Some( ch ) => self.tk().eval(( "font", "actual", font, "-displayof", self.path, option, Obj::from(ch) )),
None => self.tk().eval(( "font", "actual", font, "-displayof", self.path, option )),
}
}
pub fn font_actual_get_all<'a, Opts>( &self, font: Font<'a, Opts> ) -> InterpResult<Obj>
where Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let font = Obj::from( font );
self.tk().eval(( "font", "actual", font, "-displayof", self.path ))
}
#[cex]
pub fn font_families( &self ) -> Result!( Vec<String> throws InterpError, NotList ) {
let list = self.tk().eval(( "font", "families", "-displayof", self.path ))?;
Ok( list.get_elements()?.map( |obj| obj.get_string() ).collect() )
}
pub fn font_measure<'a, Opts>( &self, font: Font<'a, Opts>, text: impl Into<String> ) -> InterpResult<c_longlong>
where Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let font = Obj::from( font );
self.tk().longlong( self.tk().eval(( "font", "measure", font, "-displayof", self.path, text.into() ))? )
}
pub fn font_metrics<'a, Opt, Opts>( &self, font: Font<'a, Opts>, _opt: Opt ) -> InterpResult<Obj>
where Opt : TkOption
+ Into<TkFontOpt>
, Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let font = Obj::from( font );
let option = Obj::from( <Opt as TkOption>::NAME );
self.tk().eval(( "font", "metrics", font, "-displayof", self.path, option ))
}
#[cex]
pub fn font_metrics_get_all<'a, Opts>( &self, font: Font<'a, Opts> ) -> Result!( Vec<OptPair>
throws InterpError, NotList, NotSeqOf<OptPair> )
where Opts : IntoHomoTuple<TkFontOpt>
+ IntoHomoTuple<OptPair>
{
let font = Obj::from( font );
let mut opt_pairs = Vec::new();
let obj = self.tk().eval(( "font", "metrics", font, "-displayof", self.path ))?;
let mut pairs = obj.clone().get_elements()?;
while let Some( name ) = pairs.next() {
let value = if let Some( value ) = pairs.next() {
value.clone()
} else {
throw!( NotSeqOf::new( obj.clone() ));
};
let name = match name.get_string().as_str() {
"-ascent" => "ascent" ,
"-descent" => "descent" ,
"-linespace" => "linespace",
"-fixed" => "fixed" ,
_ => throw!( NotSeqOf::new( obj )),
};
opt_pairs.push( OptPair{ name, value });
}
Ok( opt_pairs )
}
}