1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::types::{Rect, Vector2};

#[derive(Clone, Debug)]
pub struct Scroll {
    pub scroll: Vector2,
    pub dragging_x: bool,
    pub dragging_y: bool,
    pub rect: Rect,
    pub inner_rect: Rect,
    pub inner_rect_previous_frame: Rect,
    pub initial_scroll: Vector2,
}
impl Scroll {
    pub fn scroll_to(&mut self, y: f32) {
        self.rect.y = y
            .max(self.inner_rect_previous_frame.y)
            .min(self.inner_rect_previous_frame.h - self.rect.h + self.inner_rect_previous_frame.y);
    }

    pub fn update(&mut self) {
        self.rect.y =
            self.rect.y.max(self.inner_rect_previous_frame.y).min(
                self.inner_rect_previous_frame.h - self.rect.h + self.inner_rect_previous_frame.y,
            );
    }
}

#[derive(Debug)]
pub enum Layout {
    Vertical,
    Horizontal,
    Free(Vector2),
}

#[derive(Debug)]
pub struct Cursor {
    pub x: f32,
    pub y: f32,
    pub start_x: f32,
    pub start_y: f32,
    pub ident: f32,
    pub scroll: Scroll,
    pub area: Rect,
    pub margin: f32,
    pub next_same_line: bool,
    pub max_row_y: f32,
}

impl Cursor {
    pub fn new(area: Rect, margin: f32) -> Cursor {
        Cursor {
            margin: margin,
            x: margin,
            y: margin,
            ident: 0.,
            start_x: margin,
            start_y: margin,
            scroll: Scroll {
                rect: Rect::new(0., 0., area.w, area.h),
                inner_rect: Rect::new(0., 0., area.w, area.h),
                inner_rect_previous_frame: Rect::new(0., 0., area.w, area.h),
                scroll: Vector2::new(0., 0.),
                dragging_x: false,
                dragging_y: false,
                initial_scroll: Vector2::new(0., 0.),
            },
            area,
	    next_same_line: false,
	    max_row_y: 0.
        }
    }

    pub fn reset(&mut self) {
        self.x = self.start_x;
        self.y = self.start_y;
	self.max_row_y = 0.;
        self.ident = 0.;
        self.scroll.inner_rect_previous_frame = self.scroll.inner_rect;
        self.scroll.inner_rect = Rect::new(0., 0., self.area.w, self.area.h);
    }

    pub fn fit(&mut self, size: Vector2, mut layout: Layout) -> Vector2 {
        let res;

	if self.next_same_line {
	    self.next_same_line = false;
	    layout = Layout::Horizontal;
	}
        match layout {
            Layout::Horizontal => {
		self.max_row_y = self.max_row_y.max(size.y);

                if self.x + size.x < self.area.w as f32 - self.margin * 2. {
                    res = Vector2::new(self.x, self.y);
                } else {
                    self.x = self.margin;
                    self.y += self.max_row_y + self.margin;
		    self.max_row_y = 0.;
                    res = Vector2::new(self.x, self.y);
                }
                self.x += size.x + self.margin;
            }
            Layout::Vertical => {
		if self.x != self.margin {
		    self.x = self.margin;
		    self.y += self.max_row_y;
		}
                res = Vector2::new(self.x, self.y);
		self.x += size.x + self.margin;
                self.max_row_y = size.y + self.margin;
            }
            Layout::Free(point) => {
                res = point;
            }
        }
        self.scroll.inner_rect = self
            .scroll
            .inner_rect
            .combine_with(Rect::new(res.x, res.y, size.x, size.y));
        res + Vector2::new(self.area.x as f32, self.area.y as f32)
            + self.scroll.scroll
            + Vector2::new(self.ident, 0.)
    }
}