tech_ui/
lib.rs

1pub mod resources;
2
3mod tabs;
4mod table;
5
6pub use tabs::{Tab,Tabs};
7
8pub use table::{TableBuilder,TableDrawer,RowRef,TableError,SoftColumn};
9
10#[derive(Debug)]
11pub struct Style {
12    name: &'static str,
13    opts: Vec<(&'static str, &'static str)>,
14}
15impl Style {
16    pub fn new(style: &'static str) -> Style {
17        Style {
18            name: style,
19            opts: Vec::new(),
20        }
21    }
22    pub fn duplicate(&self,style: &'static str) -> Style {
23        Style {
24            name: style,
25            opts: self.opts.clone(),
26        }
27    }
28    pub fn opt(mut self, opt: &'static str, value: &'static str) -> Style {
29        let mut idx = None;
30        for (i,(o,_)) in self.opts.iter().enumerate() {
31            if *o == opt { idx = Some(i); break }
32        }
33        match idx {
34            Some(i) => self.opts[i] = (opt,value),
35            None => self.opts.push((opt,value)),
36        }
37        self
38    }
39}
40impl ToString for Style {
41    fn to_string(&self) -> String {
42        match self.opts.len() {
43            0 => String::new(),
44            _ => {
45                let mut s = format!(".{} {{",self.name);
46                for (o,v) in &self.opts {
47                    s += "    ";
48                    s += o;
49                    s += ": ";
50                    s += v;
51                    s += ";\n"
52                }
53                s += "}";
54                s
55            },
56        }
57    }
58}
59
60pub fn classed<T: ToString>(class: &'static str, t: T) -> String {
61    format!("<span class='{}'>{}</span>",class,t.to_string())
62}
63
64#[derive(Debug)]
65pub struct Block {
66    class: &'static str,
67    onclick: Option<String>,
68    id: Option<String>,
69    text: Option<String>,
70    subs: Vec<Block>,
71}
72impl Block {
73    pub fn new(class: &'static str) -> Block {
74        Block {
75            class,
76            onclick: None,
77            id: None,
78            text: None,
79            subs: Vec::new(),
80        }
81    }
82    pub fn id<T: ToString>(mut self, id: T) -> Block {
83        self.id = Some(id.to_string());
84        self
85    }
86    pub fn onclick<T: ToString>(mut self, onclick: T) -> Block {
87        self.onclick = Some(onclick.to_string());
88        self
89    }
90    pub fn text<T: ToString>(mut self, t: T) -> Block {
91        self.text = Some(t.to_string());
92        self
93    }
94    pub fn sub(mut self, s: Block) -> Block {
95        self.subs.push(s);
96        self
97    }
98    pub fn sub_mut(&mut self, s: Block) {
99        self.subs.push(s);
100    }
101}
102impl ToString for Block {
103    fn to_string(&self) -> String {
104        let t = match &self.text {
105            Some(t) => t,
106            None => "",
107        };
108        let s = match self.subs.len() {
109            0 => String::new(),
110            _ => {
111                let mut s = String::new();
112                for b in &self.subs {
113                    s += &b.to_string();
114                    s += "\n"
115                }
116                s
117            },
118        };
119        match (&self.id, &self.onclick) {
120            (None,None) => format!("<div class='{}'>{}{}</div>",self.class,t,s),
121            (None, Some(oc)) => format!("<div class='{}' onclick='{}'>{}{}</div>",self.class,oc,t,s),
122            (Some(id),None) => format!("<div id='{}' class='{}'>{}{}</div>",id,self.class,t,s),
123            (Some(id), Some(oc)) => format!("<div id='{}' class='{}' onclick='{}'>{}{}</div>",id,self.class,oc,t,s),
124        }
125    }
126}
127
128
129#[derive(Debug,Default)]
130pub struct HtmlProducer {
131    title: String,
132    scripts: Vec<String>,
133    styles: Vec<Style>,
134    blocks: Vec<Block>,
135
136    tables: TableDrawer,
137    
138    css: String,
139    js: String,
140}
141impl ToString for HtmlProducer {
142    fn to_string(&self) -> String {
143        let mut style = self.css.clone();
144        style += "\n";
145        for s in &self.styles {
146            style += &s.to_string();
147            style += "\n";
148        }
149        let mut body = String::new();
150        for b in &self.blocks {
151            body += &b.to_string();
152            body += "\n";
153        }
154        let mut script = self.js.clone();
155        script += "\n";
156        for scr in &self.scripts {
157            script += scr;
158            script += "\n";
159        }
160        format!("<html>\n<head>\n<title>\n{}\n</title>\n<style>\n{}\n</style>\n<script>\n{}\n</script>\n</head>\n<body>\n{}\n</body>\n</html>\n",self.title,style,script,body)
161    }
162}
163impl HtmlProducer {
164    pub fn with_title<T: ToString>(mut self, t: T) -> HtmlProducer {
165        self.title = t.to_string();
166        self
167    }
168    pub fn with_styles(mut self, css: &String) -> HtmlProducer {
169        if self.css != "" { self.css += "\n"; }
170        self.css += css;        
171        self
172    }
173    pub fn with_scripts(mut self, js: &String) -> HtmlProducer {
174        if self.js != "" { self.js += "\n"; }
175        self.js += js;        
176        self
177    }
178    
179    pub fn push_script<T: ToString>(&mut self, t: T) {
180        self.scripts.push(t.to_string());
181    }
182    pub fn push_style(&mut self, s: Style) {
183        self.styles.push(s);
184    }
185    pub fn push_block(&mut self, b: Block) {
186        self.blocks.push(b);
187    }
188    
189    pub fn drawer(&mut self) -> &mut TableDrawer {
190        &mut self.tables
191    }
192    pub fn add_tables(&mut self, tb: &TableBuilder) {        
193        let s = tb.styles(&self.tables);
194        if s != "" {
195            if self.css != "" { self.css += "\n"; }
196            self.css += &s;
197        }
198    }
199}