shithub: libscroll

ref: 0adb432869b58347d874cd8961584817cd478c26
dir: /scroll.c/

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <frame.h>
#include "scroll.h"

enum {
	Scrollwid = 12,	/* width of scroll bar */
	Scrollgap = 4,	/* gap right of scroll bar */
};

Rectangle
scrollinit(Scroll *s, Rectangle r, Image *b, Image **cols)
{
	if(cols != nil)
		memmove(s->cols, cols, sizeof(s->cols));
	s->r = r;
	s->r.max.x = r.min.x + Scrollwid;
	s->image = b;
	r.min.x += Scrollwid + Scrollgap;
	return r;
}

void
scrollpos(Scroll *s, uint p₀, uint p₁, uint tot)
{
	Rectangle q;
	int h;

	q = s->r;
	h = Dy(q);
	s->tot = tot;
	s->p₀ = p₀;
	s->p₁ = p₁;
	if(tot > 1024*1024){
		tot >>= 10;
		p₀ >>= 10;
		p₁ >>= 10;
	}
	if(tot > 0){
		q.min.y += h*p₀/tot;
		q.max.y = q.min.y+h*(p₁-p₀)/tot;
	}
	draw(s->image, s->r, s->cols[BORD], nil, ZP);
	draw(s->image, insetrect(q, 1), s->cols[BACK], nil, ZP);
}

int
scrollactive(Scroll *s, Mouse *m)
{
	return ptinrect(m->xy, s->r) && m->buttons;
}

uint
scrollscr(Scroll *s, Mouse *m)
{
	int y, h;
	uint p₀;

	p₀ = 0;
	h = Dy(s->r);
	y = m->xy.y;
	if(y < s->r.min.y)
		y = s->r.min.y;
	if(y > s->r.max.y)
		y = s->r.max.y;
	switch(m->buttons){
	case 2:
		if(y > s->r.max.y-2)
			y = s->r.max.y-2;
		if(s->tot > 1024*1024)
			p₀ = ((s->tot>>10)*(y-s->r.min.y)/h)<<10;
		else
			p₀ = s->tot*(y-s->r.min.y)/h;
		break;
	case 1:
	case 8:
		p₀ = (s->p₁-s->p₀)*(y-s->r.min.y)/h+s->p₀;
		if(s->p₀ > p₀-s->p₀)
			p₀ = s->p₀-p₀+s->p₀;
		else
			p₀ = 0;
		break;
	case 4:
	case 16:
		p₀ = (s->p₁-s->p₀)*(y-s->r.min.y)/h+s->p₀;
		break;
	}
	return p₀;
}