DVUI

Parameters

#
self:*ScrollContainerWidget
*ScrollContainerWidget

Source

Implementation

#
pub fn processVelocity(self: *ScrollContainerWidget) void {
    // velocity is only for touch currently

    // damp the current velocity
    // exponential decay: v *= damping^secs_since
    // tweak the damping so we brake harder as the velocity slows down
    if (!self.finger_down) {
        const before = self.si.viewport.topLeft();
        {
            const damping = 0.0001 + @min(1.0, @abs(self.si.velocity.x) / 50.0) * (0.7 - 0.0001);
            self.si.velocity.x *= @exp(@log(damping) * dvui.secondsSinceLastFrame());
            if (@abs(self.si.velocity.x) > 1) {
                //std.debug.print("vel x {d}\n", .{self.si.velocity.x});
                self.si.viewport.x += self.si.velocity.x * 50 * dvui.secondsSinceLastFrame();
                dvui.refresh(null, @src(), self.data().id);
            } else {
                self.si.velocity.x = 0;
            }
        }

        {
            const damping = 0.0001 + @min(1.0, @abs(self.si.velocity.y) / 50.0) * (0.7 - 0.0001);
            self.si.velocity.y *= @exp(@log(damping) * dvui.secondsSinceLastFrame());
            if (@abs(self.si.velocity.y) > 1) {
                //std.debug.print("vel y {d}\n", .{self.si.velocity.y});
                self.si.viewport.y += self.si.velocity.y * 50 * dvui.secondsSinceLastFrame();
                dvui.refresh(null, @src(), self.data().id);
            } else {
                self.si.velocity.y = 0;
            }
        }

        if (self.init_opts.user_scroll) |us| us.* = us.*.plus(self.si.viewport.topLeft().diff(before));
    }

    // bounce back if we went too far
    // bounce back does not count for user_scroll
    {
        const max_scroll = self.si.scrollMax(.horizontal);
        if (self.si.viewport.x < 0) {
            self.si.velocity.x = 0;
            self.si.viewport.x = @min(0, @max(-20, self.si.viewport.x + 250 * dvui.secondsSinceLastFrame()));
            if (self.si.viewport.x < 0) {
                dvui.refresh(null, @src(), self.data().id);
            }
        } else if (self.si.viewport.x > max_scroll) {
            self.si.velocity.x = 0;
            self.si.viewport.x = @max(max_scroll, @min(max_scroll + 20, self.si.viewport.x - 250 * dvui.secondsSinceLastFrame()));
            if (self.si.viewport.x > max_scroll) {
                dvui.refresh(null, @src(), self.data().id);
            }
        }
    }

    {
        const max_scroll = self.si.scrollMax(.vertical);

        if (self.si.viewport.y < 0) {
            self.si.velocity.y = 0;
            self.si.viewport.y = @min(0, @max(-20, self.si.viewport.y + 250 * dvui.secondsSinceLastFrame()));
            if (self.si.viewport.y < 0) {
                dvui.refresh(null, @src(), self.data().id);
            }
        } else if (self.si.viewport.y > max_scroll) {
            self.si.velocity.y = 0;
            self.si.viewport.y = @max(max_scroll, @min(max_scroll + 20, self.si.viewport.y - 250 * dvui.secondsSinceLastFrame()));
            if (self.si.viewport.y > max_scroll) {
                dvui.refresh(null, @src(), self.data().id);
            }
        }
    }

    // might have changed
    self.frame_viewport = self.init_opts.frame_viewport orelse self.si.viewport.topLeft();
}