rustyphoenixlecture 1.5.0

This project aims to provide a simple a powerfull lecture compilation to generate html web sites
/***************************************
	Auteur : Pierre Aubert
	Mail : pierre.aubert@lapp.in2p3.fr
	Licence : CeCILL-C
****************************************/

use crate::pcontent::{
	pabstractcontent::{PAbstractContent, PAbstractLectureBackend},
	plabeler::PLabelId,
	preferenceurl::PReferenceUrl,
	pveccontent::PVecContent
};

///Cell of a table in the lecture
#[derive(Debug, Clone, Default, PartialEq)]
pub struct PContentCell{
	///Vector of children
	content: PVecContent,
}

impl PContentCell {
	///Constructor of the PContentCell
	/// # Returns
	/// Initialised PContentCell
	pub fn new() -> Self{
		PContentCell {
			content: Default::default(),
		}
	}
	///Get the content of the PContentCell
	/// # Returns
	/// Content of the PContentCell
	pub fn get_content(&self) -> &PVecContent {
		&self.content
	}
	///Get the mutable content of the PContentCell
	/// # Returns
	/// Mutable content of the PContentCell
	pub fn get_content_mut(&mut self) -> &mut PVecContent {
		&mut self.content
	}
}

impl PAbstractContent for PContentCell{
	///Say if the PContent has an embeded label
	/// # Returns
	/// True if the PContent has an embeded label, false otherwise
	fn has_embeded_label(&self) -> bool{
		false
	}
	///Get the reference url of the current PContentCell
	/// # Parameters
	/// - `current_file` : current output file of the PContentCell
	/// - `id` : id of the PContent
	/// # Returns
	/// Corresponding PReferenceUrl
	fn get_reference_url(&self, current_file: &String, id: usize) -> PReferenceUrl{
		PReferenceUrl::from_text(current_file, id, &String::from(&format!("PContentCell {}", id)))
	}
	///Convert the current struct into html
	/// # Parameters
	/// - `backend` : backend which write a lecture in files
	/// - `id` : id of the PContent
	fn to_html<TLectureBackend>(&self, backend: &mut TLectureBackend, id: &PLabelId)
		where TLectureBackend: PAbstractLectureBackend
	{
		self.content.to_html(backend, id);
	}
}

///Row of a table in the lecture
#[derive(Debug, Clone, Default, PartialEq)]
pub struct PContentRow{
	///Vector of Cells
	p_vec_cell: Vec<PContentCell>,
}

impl PContentRow {
	///Constructor of the PContentRow
	/// # Returns
	/// Initialised PContentRow
	pub fn new() -> Self{
		PContentRow {
			p_vec_cell: Default::default(),
		}
	}
	///Get the vector of Cells of the current row
	/// # Returns
	/// Vector of Cells of the current row
	pub fn get_vec_cell(&self) -> &Vec<PContentCell> {
		&self.p_vec_cell
	}
	///Get the mutable vector of Cells of the current row
	/// # Returns
	/// Mutable vector of Cells of the current row
	pub fn get_vec_cell_mut(&mut self) -> &mut Vec<PContentCell> {
		&mut self.p_vec_cell
	}
}

impl PAbstractContent for PContentRow{
	///Say if the PContent has an embeded label
	/// # Returns
	/// True if the PContent has an embeded label, false otherwise
	fn has_embeded_label(&self) -> bool{
		false
	}
	///Get the reference url of the current PContentRow
	/// # Parameters
	/// - `current_file` : current output file of the PContentRow
	/// - `id` : id of the PContent
	/// # Returns
	/// Corresponding PReferenceUrl
	fn get_reference_url(&self, current_file: &String, id: usize) -> PReferenceUrl{
		PReferenceUrl::from_text(current_file, id, &String::from(&format!("PContentRow {}", id)))
	}
	///Convert the current struct into html
	/// # Parameters
	/// - `backend` : backend which write a lecture in files
	/// - `id` : id of the PContent
	fn to_html<TLectureBackend>(&self, backend: &mut TLectureBackend, id: &PLabelId)
		where TLectureBackend: PAbstractLectureBackend
	{
		for cell in self.p_vec_cell.iter(){
			backend.write(&String::from("<td>"));
			cell.to_html(backend, id);
			backend.write(&String::from("</td>"));
		}
	}
}



///Content object of the lecture
#[derive(Debug, Clone, Default, PartialEq)]
pub struct PContentTable{
	///Vector of rows
	p_vec_row: Vec<PContentRow>,
}

impl PContentTable {
	///Constructor of the PContentTable
	/// # Returns
	/// Initialised PContentTable
	pub fn new() -> Self{
		PContentTable {
			p_vec_row: Default::default(),
		}
	}
	///Add the given cell in the last row of the table
	/// # Parameters
	/// - `cell` : cell to be added
	pub fn add_cell_in_last_row(&mut self, cell: &PContentCell){
		match self.p_vec_row.last_mut() {
			Some(last_row) => last_row.get_vec_cell_mut().push(cell.clone()),
			None => {
				let mut row = PContentRow::new();
				row.get_vec_cell_mut().push(cell.clone());
				self.p_vec_row.push(row.clone());
			}
		}
	}
	///Get the vector of rows of the current table
	/// # Returns
	/// Vector of rows of the current table
	pub fn get_vec_row(&self) -> &Vec<PContentRow> {
		&self.p_vec_row
	}
	///Get the mutable vector of rows of the current table
	/// # Returns
	/// Mutable vector of rows of the current table
	pub fn get_vec_row_mut(&mut self) -> &mut Vec<PContentRow> {
		&mut self.p_vec_row
	}
	///Check if the rows of the table have the same number of columns
	/// # Returns
	/// True if the rows of the table have the same number of columns, false otherwise
	pub fn check_table(&self) -> bool{
		let mut expected_nb_col: Option<usize> = None;
		let mut is_ok = true;
		for (i,row) in self.p_vec_row.iter().enumerate(){
			match expected_nb_col {
				Some(nb_col) => {
					if nb_col != row.p_vec_cell.len() {
						println!("PContentTable::check_table : Row {} has {} != {} which is the expected number of columns",i, row.p_vec_cell.len(), nb_col);
						is_ok = false;
					}
				},
				None => expected_nb_col = Some(row.p_vec_cell.len())
			}
		}
		return is_ok;
	}
}

impl PAbstractContent for PContentTable{
	///Say if the PContent has an embeded label
	/// # Returns
	/// True if the PContent has an embeded label, false otherwise
	fn has_embeded_label(&self) -> bool{
		false
	}
	///Get the reference url of the current PContentTable
	/// # Parameters
	/// - `current_file` : current output file of the PContentTable
	/// - `id` : id of the PContent
	/// # Returns
	/// Corresponding PReferenceUrl
	fn get_reference_url(&self, current_file: &String, id: usize) -> PReferenceUrl{
		PReferenceUrl::from_text(current_file, id, &String::from(&format!("PContentTable {}", id)))
	}
	///Convert the current struct into html
	/// # Parameters
	/// - `backend` : backend which write a lecture in files
	/// - `id` : id of the PContent
	fn to_html<TLectureBackend>(&self, backend: &mut TLectureBackend, id: &PLabelId)
		where TLectureBackend: PAbstractLectureBackend
	{
		backend.write(&String::from(&format!("<table id=\"{}\" class=\"tabularStyle\">\n", id.get_id())));
		for row in self.p_vec_row.iter(){
			backend.write(&String::from("\t<tr>"));
			row.to_html(backend, id);
			backend.write(&String::from("</tr>\n"));
		}
		backend.write(&String::from("</table>\n"));
	}
}


#[cfg(test)]
mod tests{
	use crate::pcontent::{
		PContentText, PContentType, plabeler::PLabeler, pstrbackend::PStrBackend
	};
	use super::*;
	
	///Test the PContentTable
	#[test]
	fn test_pcontent_table(){
		let mut cell = PContentCell::new();
		cell.get_content_mut().add_child(&PContentType::Text(PLabeler::new(24, &PContentText::new(&String::from("O")))));
		
		let mut row = PContentRow::new();
		row.get_vec_cell_mut().push(cell);
		
		let mut table = PContentTable::new();
		table.get_vec_row_mut().push(row);
		let mut backend = PStrBackend::new();
		table.to_html(&mut backend, &PLabelId::new(42));
		assert_eq!(backend.get_body(), &String::from("<table id=\"42\" class=\"tabularStyle\">\n\t<tr><td>O</td></tr>\n</table>\n"));
		assert!(table.check_table());
	}
	
	///Test a broken table
	#[test]
	fn test_broken_pcontent_table(){
		let mut cell = PContentCell::new();
		cell.get_content_mut().add_child(&PContentType::Text(PLabeler::new(24, &PContentText::new(&String::from("O")))));
		
		let mut row1 = PContentRow::new();
		row1.get_vec_cell_mut().push(cell.clone());
		
		let mut row2 = PContentRow::new();
		row2.get_vec_cell_mut().push(cell.clone());
		row2.get_vec_cell_mut().push(cell.clone());
		
		let mut table = PContentTable::new();
		table.get_vec_row_mut().push(row1);
		table.get_vec_row_mut().push(row2);
		assert!(!table.check_table());
	}
}