tuix_widgets/inputs/
textbox.rs

1use crate::common::*;
2
3use femtovg::{renderer::OpenGl, Align, Baseline, Canvas, Color, Paint, Path, Solidity};
4
5use crate::Key;
6
7#[derive(Debug, Clone, PartialEq)]
8pub enum TextboxEvent {
9    SetValue(String),
10    ValueChanged(String),
11    ResetValue,
12    Clear,
13}
14
15//impl Message for TextboxEvent {}
16
17pub struct Textbox {
18    entity: Entity,
19    pub text: String,
20
21    buffer: String,
22
23    units: String,
24    //multiplier: f32,
25
26    select_pos: u32,
27    cursor_pos: u32,
28    edit: bool,
29    hitx: f32,
30    dragx: f32,
31
32    // Events
33    on_change: Option<Box<dyn Fn(&mut Self, &mut State, Entity)>>,
34    on_submit: Option<Box<dyn Fn(&mut Self, &mut State, Entity)>>,
35}
36
37impl Textbox {
38    pub fn new(text: &str) -> Self {
39        // id.set_text(state, "Test".to_string())
40        //     .set_background(state, nanovg::Color::from_rgb(100, 50, 50));
41
42        Textbox {
43            entity: Entity::null(),
44
45            text: text.to_string(),
46
47            buffer: String::new(),
48
49            units: String::new(),
50
51            //multiplier: 1.0,
52
53            select_pos: 0,
54            cursor_pos: 0,
55            edit: false,
56            hitx: -1.0,
57            dragx: -1.0,
58
59            on_change: None,
60            on_submit: None,
61        }
62    }
63
64    pub fn with_units(mut self, uints: &str) -> Self {
65        self.units = uints.to_string();
66
67        self
68    }
69
70    pub fn on_change<F>(mut self, on_change: F) -> Self
71    where
72        F: 'static + Fn(&mut Self, &mut State, Entity),
73    {
74        self.on_change = Some(Box::new(on_change));
75
76        self
77    }
78
79    pub fn on_submit<F>(mut self, on_submit: F) -> Self
80    where
81        F: 'static + Fn(&mut Self, &mut State, Entity),
82    {
83        self.on_submit = Some(Box::new(on_submit));
84
85        self
86    }
87    // pub fn set_enabled(&self, state: &mut WidgetState, val: bool) {
88    //     if val {
89    //         self.id
90    //             .set_background(state, nanovg::Color::from_rgb(100, 50, 50));
91    //     } else {
92    //         self.id
93    //             .set_background(state, nanovg::Color::from_rgb(50, 50, 100));
94    //     }
95    // }
96}
97
98impl Widget for Textbox {
99    type Ret = Entity;
100    type Data = String;
101    fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret {
102        entity.set_text(state, &(self.text.to_owned() + &self.units));
103
104        self.entity = entity;
105
106        entity.set_clip_widget(state, entity);
107
108        entity.set_element(state, "textbox")
109    }
110
111    fn on_event(&mut self, state: &mut State, entity: Entity, event: &mut Event) {
112        if let Some(textbox_event) = event.message.downcast::<TextboxEvent>() {
113            match textbox_event {
114                TextboxEvent::SetValue(val) => {
115                    if event.target == entity {
116                        entity.set_text(state, &(val.to_owned() + &self.units));
117
118                        // state.insert_event(
119                        //     Event::new(WindowEvent::Restyle).target(Entity::new(0, 0)),
120                        // );
121
122                        state.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
123                    }
124                }
125
126                TextboxEvent::Clear => {
127                    self.text.clear();
128                    self.buffer.clear();
129                    entity.set_text(state, "");
130                    state.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
131                }
132
133                // TextboxEvent::ResetValue => {
134                //     if let Some(text_data) = state.style.text.get_mut(entity) {
135                //         text_data.text = self.buffer.clone();
136                //     }
137                // }
138                _ => {}
139            }
140        }
141
142        let text_data = state.style.text.get(entity).cloned().unwrap_or_default();
143
144        if let Some(window_event) = event.message.downcast::<WindowEvent>() {
145            match window_event {
146                WindowEvent::MouseMove(x, _) => {
147                    if self.hitx != -1.0 {
148                        self.dragx = *x;
149
150                        // state.insert_event(
151                        //     Event::new(WindowEvent::Restyle).target(Entity::new(0, 0)),
152                        // );
153
154                        state.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
155                    }
156                }
157
158                WindowEvent::MouseDown(button) => {
159                    if entity == state.hovered {
160                        if self.edit == false && !entity.is_disabled(state) {
161                            self.cursor_pos = text_data.len() as u32;
162                            self.select_pos = 0;
163                            self.buffer = text_data.clone();
164                            //state.captured = entity;
165                            state.capture(entity);
166                            //self.edit = true;
167                            entity.set_active(state, true);
168                            state.set_focus(entity);
169                            
170                        }
171                        if self.edit == true {
172                            self.hitx = state.mouse.cursorx;
173                            self.dragx = state.mouse.cursorx;
174                        }
175                        self.edit = true;
176
177                        // state.insert_event(
178                        //     Event::new(WindowEvent::Restyle).target(Entity::new(0, 0)),
179                        // );
180
181                        state.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
182                    } else {
183
184                        self.edit = false;
185                        entity.set_active(state, false);
186
187                        state.insert_event(
188                            Event::new(TextboxEvent::ValueChanged(text_data.clone()))
189                                .target(entity),
190                        );
191
192                        // state.insert_event(
193                        //     Event::new(WindowEvent::Restyle).target(Entity::new(0, 0)),
194                        // );
195
196                        state.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
197
198                        if state.captured == entity {
199                            state.insert_event(
200                                Event::new(WindowEvent::MouseDown(*button)).target(state.hovered),
201                            );
202                        }
203
204                        //state.captured = Entity::null();
205                        state.release(entity);
206                    }
207                }
208
209                WindowEvent::MouseUp(_) => {
210                    self.hitx = -1.0;
211                }
212
213                WindowEvent::KeyDown(_, key) => {
214                    //println!("Code: {:?} Key: {:?}", code, key);
215
216                    
217                    if *key == Some(Key::ArrowLeft) {
218                        if self.edit {
219                            self.hitx = -1.0;
220                            if self.cursor_pos > 0 {
221                                self.cursor_pos -= 1;
222                            }
223                            if !state.modifiers.shift {
224                                self.select_pos = self.cursor_pos;
225                            }
226
227                            // state.insert_event(
228                            //     Event::new(WindowEvent::Restyle).target(Entity::new(0, 0)),
229                            // );
230
231                            state.insert_event(
232                                Event::new(WindowEvent::Redraw).target(Entity::root()),
233                            );
234                        }
235                    }
236
237                    if *key == Some(Key::ArrowRight) {
238                        if self.edit {
239                            self.hitx = -1.0;
240                            if self.cursor_pos < text_data.len() as u32 {
241                                self.cursor_pos += 1;
242                            }
243                            if !state.modifiers.shift {
244                                self.select_pos = self.cursor_pos;
245                            }
246
247                            // state.insert_event(
248                            //     Event::new(WindowEvent::Restyle).target(Entity::new(0, 0)),
249                            // );
250
251                            state.insert_event(
252                                Event::new(WindowEvent::Redraw).target(Entity::root()),
253                            );
254                        }
255                    }
256                    if *key == Some(Key::Backspace) || *key == Some(Key::Delete) {
257                        if self.edit {
258                            let start = std::cmp::min(self.select_pos, self.cursor_pos) as usize;
259                            let end = std::cmp::max(self.select_pos, self.cursor_pos) as usize;
260
261                            //let start = text_data.select_pos as usize;
262                            //let end = text_data.cursor_pos as usize;
263                            if start == end && self.cursor_pos > 0 {
264                                if *key == Some(Key::Backspace) {
265                                    if let Some(txt) = state.style.text.get_mut(entity) {
266                                        txt.remove((self.cursor_pos - 1) as usize);
267                                        //txt.pop();
268                                    }
269                                    self.cursor_pos -= 1;
270                                    self.select_pos -= 1;
271
272                                } else {
273                                    if (self.cursor_pos as usize) < (self.text.len()) {
274                                        if let Some(txt) = state.style.text.get_mut(entity) {
275                                            txt.remove((self.cursor_pos) as usize);
276                                            //txt.pop();
277                                        }
278                                    }
279                                }
280                                
281
282                                
283                            } else {
284                                
285                                if let Some(txt) = state.style.text.get_mut(entity) {
286                                    txt.replace_range(start..end, "");
287                                }
288                                self.cursor_pos = start as u32;
289                                self.select_pos = start as u32;
290                            }
291
292                            self.text = state.style.text.get(entity).unwrap().to_owned();
293
294                            // state.insert_event(
295                            //     Event::new(WindowEvent::Restyle).target(Entity::new(0, 0)),
296                            // );
297
298                            if let Some(callback) = self.on_change.take() {
299                                (callback)(self, state, entity);
300                                self.on_change = Some(callback);
301                            }
302
303                            state.insert_event(
304                                Event::new(WindowEvent::Redraw).target(Entity::root()),
305                            );
306                        }
307                    }
308                    if *key == Some(Key::Enter) {
309                        if self.edit {
310                            //text_data.buffer = text_data.text.clone();
311                            state.insert_event(
312                                Event::new(TextboxEvent::ValueChanged(text_data.clone()))
313                                    .target(entity),
314                            );
315
316                            if let Some(callback) = self.on_submit.take() {
317                                (callback)(self, state, entity);
318                                self.on_submit = Some(callback);
319                            }
320
321                            self.edit = false;
322                            entity.set_active(state, false);
323                            state.release(entity);
324
325
326                            state.insert_event(
327                                Event::new(WindowEvent::Redraw).target(Entity::root()),
328                            );
329                        }
330                    }
331                    if *key == Some(Key::Escape) {
332                        if self.edit {
333                            self.text = self.buffer.clone();
334                            self.edit = false;
335                            entity.set_active(state, false);
336
337                            // state.insert_event(
338                            //     Event::new(WindowEvent::Restyle).target(Entity::new(0, 0)),
339                            // );
340
341                            // TODO - Change this to a 'Cancelled' callback
342                            // if let Some(callback) = self.on_submit.take() {
343                            //     (callback)(self, state, entity);
344                            //     self.on_submit = Some(callback);
345                            // }
346
347                            state.insert_event(
348                                Event::new(WindowEvent::Redraw).target(Entity::root()),
349                            );
350                        }
351                    }
352                }
353
354                WindowEvent::CharInput(input) => {
355                    if *input as u8 != 8 && *input as u8 != 13 && *input as u8 != 127 {
356                        // Ignore input when ctrl is being held
357                        if state.modifiers.ctrl {
358                            return;
359                        }
360                        if self.edit {
361                            //println!("Input: {}", input);
362                            let start = std::cmp::min(self.select_pos, self.cursor_pos) as usize;
363                            let end = std::cmp::max(self.select_pos, self.cursor_pos) as usize;
364                            //let start = text_data.select_pos as usize;
365                            //let end = text_data.cursor_pos as usize;
366                            if start == end {
367                                if let Some(txt) = state.style.text.get_mut(entity) {
368                                    txt.insert(start, *input);
369                                }
370
371                                //text_data.text.remove((text_data.cursor_pos - 1) as usize);
372                                self.cursor_pos += 1;
373                                self.select_pos += 1;
374                            } else {
375                                if let Some(txt) = state.style.text.get_mut(entity) {
376                                    txt.replace_range(start..end, &input.to_string());
377                                }
378                                self.cursor_pos = (start + 1) as u32;
379                                self.select_pos = (start + 1) as u32;
380                            }
381
382                            self.text = state.style.text.get(entity).unwrap().to_owned();
383
384                            if let Some(callback) = self.on_change.take() {
385                                (callback)(self, state, entity);
386                                self.on_change = Some(callback);
387                            }
388
389                            // state.insert_event(
390                            //     Event::new(WindowEvent::Restyle).target(Entity::new(0, 0)),
391                            // );
392
393                            state.insert_event(
394                                Event::new(WindowEvent::Redraw).target(Entity::root()),
395                            );
396                        }
397                    }
398                }
399
400                WindowEvent::FocusIn => {
401                    if !self.edit {
402                        self.cursor_pos = text_data.len() as u32;
403                        self.select_pos = 0;
404                        self.buffer = text_data.clone();
405                        self.edit = true;
406                    }
407                }
408
409
410                WindowEvent::FocusOut => {
411                    self.edit = false;
412                    entity.set_active(state, false);
413     
414                    state.release(entity);
415
416                    // if let Some(callback) = self.on_submit.take() {
417                    //     (callback)(self, state, entity);
418                    //     self.on_submit = Some(callback);
419                    // }
420
421
422                    state.insert_event(
423                        Event::new(WindowEvent::Redraw).target(Entity::root()),
424                    );
425                }
426
427                WindowEvent::MouseCaptureOutEvent => {
428                    //println!("Mouse Capture Out");
429                    self.edit = false;
430                    entity.set_active(state, false);
431                    //state.release(entity);
432
433                    // if let Some(callback) = self.on_submit.take() {
434                    //     (callback)(self, state, entity);
435                    //     self.on_submit = Some(callback);
436                    // }
437
438
439                    state.insert_event(
440                        Event::new(WindowEvent::Redraw).target(Entity::root()),
441                    );
442                }
443
444                _ => {}
445            }
446        }
447    }
448
449
450    fn on_update(&mut self, state: &mut State, entity: Entity, data: &Self::Data) {
451        self.text = data.to_string();
452        entity.set_text(state, &self.text);
453    }
454
455    fn on_draw(
456        &mut self,
457        state: &mut State,
458        entity: Entity,
459        canvas: &mut Canvas<OpenGl>,
460        //images: &HashMap<String, nanovg::Image>,
461    ) {
462        // Skip window
463        if entity == Entity::root() {
464            return;
465        }
466
467        // Skip invisible widgets
468        if state.data.get_visibility(entity) == Visibility::Invisible {
469            //println!("Invisible: {}", entity);
470            return;
471        }
472
473        // Skip widgets that have 0 opacity
474        if state.data.get_opacity(entity) == 0.0 {
475            //println!("Zero Opacity: {}", entity);
476            return;
477        }
478
479        let posx = state.data.get_posx(entity);
480        let posy = state.data.get_posy(entity);
481        let width = state.data.get_width(entity);
482        let height = state.data.get_height(entity);
483
484        let padding_left = match state.style.child_left.get(entity).unwrap_or(&Units::Auto) {
485            Units::Pixels(val) => val,
486            _ => &0.0,
487        };
488
489        let padding_right = match state.style.child_right.get(entity).unwrap_or(&Units::Auto) {
490            Units::Pixels(val) => val,
491            _ => &0.0,
492        };
493
494        // let padding_top = match state.style.child_top.get(entity).unwrap_or(&Units::Auto) {
495        //     Units::Pixels(val) => val,
496        //     _ => &0.0,
497        // };
498
499        // let padding_bottom = match state.style.child_bottom.get(entity).unwrap_or(&Units::Auto) {
500        //     Units::Pixels(val) => val,
501        //     _ => &0.0,
502        // };
503
504        let background_color = state
505            .style
506            .background_color
507            .get(entity)
508            .cloned()
509            .unwrap_or_default();
510
511        let font_color = state
512            .style
513            .font_color
514            .get(entity)
515            .cloned()
516            .unwrap_or(crate::Color::rgb(255, 255, 255));
517
518        let border_color = state
519            .style
520            .border_color
521            .get(entity)
522            .cloned()
523            .unwrap_or_default();
524
525        let parent = state
526            .tree
527            .get_parent(entity)
528            .expect("Failed to find parent somehow");
529
530        let parent_width = state.data.get_width(parent);
531        let parent_height = state.data.get_height(parent);
532
533        let border_radius_top_left = match state
534            .style
535            .border_radius_top_left
536            .get(entity)
537            .cloned()
538            .unwrap_or_default()
539        {
540            Units::Pixels(val) => val,
541            Units::Percentage(val) => parent_width * val,
542            _ => 0.0,
543        };
544
545        let border_radius_top_right = match state
546            .style
547            .border_radius_top_right
548            .get(entity)
549            .cloned()
550            .unwrap_or_default()
551        {
552            Units::Pixels(val) => val,
553            Units::Percentage(val) => parent_width * val,
554            _ => 0.0,
555        };
556
557        let border_radius_bottom_left = match state
558            .style
559            .border_radius_bottom_left
560            .get(entity)
561            .cloned()
562            .unwrap_or_default()
563        {
564            Units::Pixels(val) => val,
565            Units::Percentage(val) => parent_width * val,
566            _ => 0.0,
567        };
568
569        let border_radius_bottom_right = match state
570            .style
571            .border_radius_bottom_right
572            .get(entity)
573            .cloned()
574            .unwrap_or_default()
575        {
576            Units::Pixels(val) => val,
577            Units::Percentage(val) => parent_width * val,
578            _ => 0.0,
579        };
580
581        let opacity = state.data.get_opacity(entity);
582
583        let mut background_color: femtovg::Color = background_color.into();
584        background_color.set_alphaf(background_color.a * opacity);
585
586        let mut border_color: femtovg::Color = border_color.into();
587        border_color.set_alphaf(border_color.a * opacity);
588
589        let border_width = match state
590            .style
591            .border_width
592            .get(entity)
593            .cloned()
594            .unwrap_or_default()
595        {
596            Units::Pixels(val) => val,
597            Units::Percentage(val) => parent_width * val,
598            _ => 0.0,
599        };
600
601        // Skip widgets with no width or no height
602        if width == 0.0 || height == 0.0 {
603            return;
604        }
605
606        // Apply transformations
607        //let transform = state.data.get_transform(entity);
608
609        canvas.save();
610        
611        //canvas.set_transform(transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]);
612        canvas.translate(posx, posy);
613
614        //let pt = canvas.transform().inversed().transform_point(posx + width / 2.0, posy + height / 2.0);
615        //canvas.translate(posx + width / 2.0, posy + width / 2.0);
616        // canvas.translate(pt.0, pt.1);
617        // canvas.scale(1.0, scaley.0);
618        // canvas.translate(-pt.0, -pt.1);
619
620        // Apply Scissor
621        //let clip_region = state.data.get_clip_region(entity);
622        // canvas.scissor(
623        //     clip_region.x - posx,
624        //     clip_region.y - posy,
625        //     clip_region.w,
626        //     clip_region.h,
627        // );
628
629        let outer_shadow_h_offset = match state
630            .style
631            .outer_shadow_h_offset
632            .get(entity)
633            .cloned()
634            .unwrap_or_default()
635        {
636            Units::Pixels(val) => val,
637            Units::Percentage(val) => parent_width * val,
638            _ => 0.0,
639        };
640
641        let outer_shadow_v_offset = match state
642            .style
643            .outer_shadow_v_offset
644            .get(entity)
645            .cloned()
646            .unwrap_or_default()
647        {
648            Units::Pixels(val) => val,
649            Units::Percentage(val) => parent_height * val,
650            _ => 0.0,
651        };
652
653        let outer_shadow_blur = match state
654            .style
655            .outer_shadow_blur
656            .get(entity)
657            .cloned()
658            .unwrap_or_default()
659        {
660            Units::Pixels(val) => val,
661            Units::Percentage(val) => parent_height * val,
662            _ => 0.0,
663        };
664
665        let outer_shadow_color = state
666            .style
667            .outer_shadow_color
668            .get(entity)
669            .cloned()
670            .unwrap_or_default();
671
672        let mut outer_shadow_color: femtovg::Color = outer_shadow_color.into();
673        outer_shadow_color.set_alphaf(outer_shadow_color.a * opacity);
674
675        let inner_shadow_h_offset = match state
676            .style
677            .inner_shadow_h_offset
678            .get(entity)
679            .cloned()
680            .unwrap_or_default()
681        {
682            Units::Pixels(val) => val,
683            Units::Percentage(val) => parent_width * val,
684            _ => 0.0,
685        };
686
687        let inner_shadow_v_offset = match state
688            .style
689            .inner_shadow_v_offset
690            .get(entity)
691            .cloned()
692            .unwrap_or_default()
693        {
694            Units::Pixels(val) => val,
695            Units::Percentage(val) => parent_height * val,
696            _ => 0.0,
697        };
698
699        let inner_shadow_blur = match state
700            .style
701            .inner_shadow_blur
702            .get(entity)
703            .cloned()
704            .unwrap_or_default()
705        {
706            Units::Pixels(val) => val,
707            Units::Percentage(val) => parent_height * val,
708            _ => 0.0,
709        };
710
711        let inner_shadow_color = state
712            .style
713            .inner_shadow_color
714            .get(entity)
715            .cloned()
716            .unwrap_or_default();
717
718        let mut inner_shadow_color: femtovg::Color = inner_shadow_color.into();
719        inner_shadow_color.set_alphaf(inner_shadow_color.a * opacity);
720
721        // Draw outer shadow
722        let mut path = Path::new();
723        path.rect(
724            0.0 - outer_shadow_blur + outer_shadow_h_offset,
725            0.0 - outer_shadow_blur + outer_shadow_v_offset,
726            width + 2.0 * outer_shadow_blur,
727            height + 2.0 * outer_shadow_blur,
728        );
729        path.rounded_rect_varying(
730            0.0,
731            0.0,
732            width,
733            height,
734            border_radius_top_left,
735            border_radius_top_right,
736            border_radius_bottom_right,
737            border_radius_bottom_left,
738        );
739        path.solidity(Solidity::Hole);
740
741        let paint = Paint::box_gradient(
742            0.0 + outer_shadow_h_offset,
743            0.0 + outer_shadow_v_offset,
744            width,
745            height,
746            border_radius_top_left,
747            outer_shadow_blur,
748            outer_shadow_color,
749            femtovg::Color::rgba(0, 0, 0, 0),
750        );
751
752        canvas.fill_path(&mut path, paint);
753
754        let mut path = Path::new();
755
756        if border_radius_bottom_left == (width - 2.0 * border_width) / 2.0
757            && border_radius_bottom_right == (width - 2.0 * border_width) / 2.0
758            && border_radius_top_left == (width - 2.0 * border_width) / 2.0
759            && border_radius_top_right == (width - 2.0 * border_width) / 2.0
760        {
761            path.circle(
762                0.0 + (border_width / 2.0) + (width - border_width) / 2.0,
763                0.0 + (border_width / 2.0) + (height - border_width) / 2.0,
764                width / 2.0,
765            );
766        } else {
767            // Draw rounded rect
768            path.rounded_rect_varying(
769                0.0 + (border_width / 2.0),
770                0.0 + (border_width / 2.0),
771                width - border_width,
772                height - border_width,
773                border_radius_top_left,
774                border_radius_top_right,
775                border_radius_bottom_right,
776                border_radius_bottom_left,
777            );
778        }
779
780        // Fill with background color
781        let mut paint = Paint::color(background_color);
782
783        // Gradient overrides background color
784        if let Some(background_gradient) = state.style.background_gradient.get_mut(entity) {
785            let (start_x, start_y, end_x, end_y) = match background_gradient.direction {
786                Direction::LeftToRight => (0.0, 0.0, width, 0.0),
787                Direction::TopToBottom => (0.0, 0.0, 0.0, height),
788                _ => (0.0, 0.0, width, 0.0),
789            };
790
791            paint = Paint::linear_gradient_stops(
792                start_x,
793                start_y,
794                end_x,
795                end_y,
796                background_gradient
797                    .get_stops(parent_width)
798                    .iter()
799                    .map(|stop| {
800                        let col: femtovg::Color = stop.1.into();
801                        (stop.0, col)
802                    })
803                    .collect::<Vec<_>>()
804                    .as_slice(),
805            );
806        }
807
808        // Fill the quad
809        canvas.fill_path(&mut path, paint);
810
811        // Draw border
812        let mut paint = Paint::color(border_color);
813        paint.set_line_width(border_width);
814        canvas.stroke_path(&mut path, paint);
815
816        // Draw inner shadow
817        let mut path = Path::new();
818        path.rounded_rect_varying(
819            0.0,
820            0.0,
821            width,
822            height,
823            border_radius_top_left,
824            border_radius_top_right,
825            border_radius_bottom_left,
826            border_radius_bottom_right,
827        );
828
829        let paint = Paint::box_gradient(
830            0.0 + inner_shadow_h_offset,
831            0.0 + inner_shadow_v_offset,
832            width,
833            height,
834            border_radius_top_left,
835            inner_shadow_blur,
836            femtovg::Color::rgba(0, 0, 0, 0),
837            inner_shadow_color,
838        );
839        canvas.fill_path(&mut path, paint);
840
841        let mut font_color: femtovg::Color = font_color.into();
842        font_color.set_alphaf(font_color.a * opacity);
843
844        canvas.translate(-posx, -posy);
845        canvas.restore();
846
847        canvas.save();
848        //canvas.set_transform(transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]);
849        //canvas.scissor(clip_region.x, clip_region.y, clip_region.w, clip_region.h);
850
851        if let Some(text) = state.style.text.get_mut(entity) {
852            let font = state.style.font.get(entity).cloned().unwrap_or_default();
853
854            let font_id = match font.as_ref() {
855                "sans" => state.fonts.regular.unwrap(),
856                "icons" => state.fonts.icons.unwrap(),
857                _ => state.fonts.regular.unwrap(),
858            };
859
860            let mut x = posx;
861            let mut y = posy;
862            //let mut sx = posx;
863            let mut sy = posy;
864
865            let text_string = text.to_owned();
866
867            let font_size = state.style.font_size.get(entity).cloned().unwrap_or(16.0);
868
869            let mut paint = Paint::color(font_color);
870            paint.set_font_size(font_size);
871            paint.set_font(&[font_id]);
872
873            let font_metrics = canvas
874                .measure_font(paint)
875                .expect("Failed to read font metrics");
876
877            // TODO - Move this to a text layout system and include constraints
878            let child_left = state
879                .style
880                .child_left
881                .get(entity)
882                .cloned()
883                .unwrap_or_default();
884            let child_right = state
885                .style
886                .child_right
887                .get(entity)
888                .cloned()
889                .unwrap_or_default();
890            let child_top = state
891                .style
892                .child_top
893                .get(entity)
894                .cloned()
895                .unwrap_or_default();
896            let child_bottom = state
897                .style
898                .child_bottom
899                .get(entity)
900                .cloned()
901                .unwrap_or_default();
902
903            let align = match child_left {
904                Units::Pixels(val) => match child_right {
905                    Units::Stretch(_) => {
906                        x += val + border_width;
907                        Align::Left
908                    }
909
910                    _ => Align::Left,
911                },
912
913                Units::Stretch(_) => match child_right {
914                    Units::Pixels(val) => {
915                        x += width - val - border_width;
916                        Align::Right
917                    }
918
919                    Units::Stretch(_) => {
920                        x += 0.5 * width;
921                        Align::Center
922                    }
923
924                    _ => Align::Right,
925                },
926
927                _ => Align::Left,
928            };
929
930            let baseline = match child_top {
931                Units::Pixels(val) => match child_bottom {
932                    Units::Stretch(_) => {
933                        y += val + border_width;
934                        Baseline::Top
935                    }
936
937                    _ => Baseline::Top,
938                },
939
940                Units::Stretch(_) => match child_bottom {
941                    Units::Pixels(val) => {
942                        y += height - val - border_width;
943                        sy = y - font_metrics.height();
944                        Baseline::Bottom
945                    }
946
947                    Units::Stretch(_) => {
948                        y += 0.5 * height;
949                        sy = y - font_metrics.height() * 0.5;
950                        Baseline::Middle
951                    }
952
953                    _ => Baseline::Top,
954                },
955
956                _ => Baseline::Top,
957            };
958
959            paint.set_text_align(align);
960            paint.set_text_baseline(baseline);
961
962            if let Ok(res) = canvas.fill_text(x, y, &text_string, paint) {
963                let text_width = res.width();
964                //let mut glyph_positions = res.glyphs.iter().peekable();
965
966                let mut caretx = x;
967
968                let mut selectx = caretx;
969
970                if self.edit {
971                    let startx = if let Some(first_glyph) = res.glyphs.first() {
972                        first_glyph.x
973                    } else {
974                        0.0 + padding_right
975                    };
976                    //let startx = x - text_width / 2.0;
977                    let endx = startx + text_width;
978
979                    if self.hitx != -1.0 {
980                        //let endx = res.glyphs.last().unwrap().x + res.glyphs.last().unwrap().w;
981
982                        selectx = if self.hitx < startx + text_width / 2.0 {
983                            self.select_pos = 0;
984                            startx
985                        } else {
986                            self.select_pos = text.len() as u32;
987                            endx
988                        };
989
990                        caretx = if self.dragx < startx + text_width / 2.0 {
991                            self.cursor_pos = 0;
992                            startx
993                        } else {
994                            self.cursor_pos = text.len() as u32;
995                            endx
996                        };
997
998                        let mut n = 0;
999                        let mut px = x + padding_left;
1000
1001                        for glyph in res.glyphs.iter() {
1002                            let left_edge = glyph.x;
1003                            let right_edge = left_edge + glyph.width;
1004                            let gx = left_edge * 0.3 + right_edge * 0.7;
1005
1006                            // if n == 0 && self.hitx <= glyph.x {
1007                            //     selectx = left_edge;
1008                            //     self.select_pos = 0;
1009                            // }
1010
1011                            // if n == res.glyphs.len() as u32 && self.hitx >= glyph.x + glyph.width {
1012                            //     selectx = right_edge;
1013                            //     self.select_pos = n;
1014                            // }
1015
1016                            // if n == 0 && self.dragx <= glyph.x {
1017                            //     caretx = left_edge;
1018                            //     self.cursor_pos = 0;
1019                            // }
1020
1021                            // if n == res.glyphs.len() as u32 && self.hitx >= glyph.x + glyph.width {
1022                            //     caretx = right_edge;
1023                            //     self.cursor_pos = n;
1024                            // }
1025
1026                            if self.hitx >= px && self.hitx < gx {
1027                                selectx = left_edge;
1028
1029                                self.select_pos = n;
1030                            }
1031
1032                            if self.dragx >= px && self.dragx < gx {
1033                                caretx = left_edge;
1034
1035                                self.cursor_pos = n;
1036                            }
1037
1038                            px = gx;
1039                            n += 1;
1040                        }
1041                    } else {
1042                        let mut n = 0;
1043                        //println!("cursor: {}", self.cursor_pos);
1044                        //let mut start_x = 0.0;
1045
1046                        for glyph in res.glyphs.iter() {
1047                            if n == self.cursor_pos {
1048                                caretx = glyph.x;
1049                            }
1050
1051                            if n == self.select_pos {
1052                                selectx = glyph.x;
1053                            }
1054
1055                            n += 1;
1056                        }
1057
1058                        if self.cursor_pos as usize == text.len() && text.len() != 0 {
1059                            caretx = endx;
1060                        }
1061
1062                        if self.select_pos as usize == text.len() && text.len() != 0 {
1063                            selectx = endx;
1064                        }
1065                    }
1066
1067                    //Draw selection
1068                    let select_width = (caretx - selectx).abs();
1069                    if selectx > caretx {
1070                        let mut path = Path::new();
1071                        path.rect(caretx, sy, select_width, font_metrics.height());
1072                        canvas.fill_path(&mut path, Paint::color(Color::rgba(0, 0, 0, 64)));
1073                    } else if caretx > selectx {
1074                        let mut path = Path::new();
1075                        path.rect(selectx, sy, select_width, font_metrics.height());
1076                        canvas.fill_path(&mut path, Paint::color(Color::rgba(0, 0, 0, 64)));
1077                    }
1078
1079                    // Draw Caret
1080                    let mut path = Path::new();
1081                    path.rect(caretx.floor(), sy, 1.0, font_metrics.height());
1082                    canvas.fill_path(&mut path, Paint::color(Color::rgba(247, 76, 0, 255)));
1083
1084                    // let mut path = Path::new();
1085                    // path.rect(endx, y - 0.25 * height, 1.0, height * 0.5);
1086                    // canvas.fill_path(&mut path, Paint::color(Color::rgba(255, 0, 0, 255)));
1087                }
1088            }
1089        }
1090        canvas.restore();
1091    }
1092}