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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
#include <panel.h>
#include "pldefs.h"
typedef struct Scrollbar Scrollbar;
struct Scrollbar{
int dir; /* HORIZ or VERT */
int lo, hi; /* setting, in screen coordinates */
int buttons; /* saved mouse buttons for transmittal to scrollee */
Rectangle interior;
Point minsize;
};
#define SBWID 15 /* should come from draw.c? */
void pl_drawscrollbar(Panel *p){
Scrollbar *sp;
sp=p->data;
sp->interior=pl_outline(p->b, p->r, SUP); /* SUP was p->state */
pl_sliderupd(p->b, sp->interior, sp->dir, sp->lo, sp->hi);
}
int pl_hitscrollbar(Panel *g, Mouse *m){
int oldstate, pos, len, dy;
Point ul, size;
Scrollbar *sp;
sp=g->data;
ul=g->r.min;
size=subpt(g->r.max, g->r.min);
pl_interior(g->state, &ul, &size);
oldstate=g->state;
if(!(g->flags & USERFL) && (m->buttons&OUT || !ptinrect(m->xy, g->r))){
m->buttons&=~OUT;
g->state=UP;
goto out;
}
if(sp->dir==HORIZ){
pos=m->xy.x-ul.x;
len=size.x;
}
else{
pos=m->xy.y-ul.y;
len=size.y;
}
if(pos<0) pos=0;
else if(pos>len) pos=len;
if(m->buttons&7){
g->state=DOWN;
sp->buttons=m->buttons;
switch(m->buttons){
case 1:
dy=pos*(sp->hi-sp->lo)/len;
pl_sliderupd(g->b, sp->interior, sp->dir, sp->lo-dy,
sp->hi-dy);
break;
case 2:
if(g->scrollee && g->scrollee->scroll)
g->scrollee->scroll(g->scrollee, sp->dir,
m->buttons, pos, len);
break;
case 4:
dy=pos*(sp->hi-sp->lo)/len;
pl_sliderupd(g->b, sp->interior, sp->dir, sp->lo+dy,
sp->hi+dy);
break;
}
}
else{
if(!(sp->buttons&2) && g->state==DOWN && g->scrollee && g->scrollee->scroll)
g->scrollee->scroll(g->scrollee, sp->dir, sp->buttons,
pos, len);
g->state=UP;
}
out:
if(oldstate!=g->state) pldraw(g, g->b);
return g->state==DOWN;
}
void pl_typescrollbar(Panel *p, Rune c){
USED(p, c);
}
Point pl_getsizescrollbar(Panel *p, Point children){
USED(children);
return pl_boxsize(((Scrollbar *)p->data)->minsize, p->state);
}
void pl_childspacescrollbar(Panel *p, Point *ul, Point *size){
USED(p, ul, size);
}
/*
* Arguments lo, hi and len are in the scrollee's natural coordinates
*/
void pl_setscrollbarscrollbar(Panel *p, int lo, int hi, int len){
Point ul, size;
int mylen;
Scrollbar *sp;
sp=p->data;
ul=p->r.min;
size=subpt(p->r.max, p->r.min);
pl_interior(p->state, &ul, &size);
mylen=sp->dir==HORIZ?size.x:size.y;
if(len==0) len=1;
sp->lo=lo*mylen/len;
sp->hi=hi*mylen/len;
if(sp->lo<0) sp->lo=0;
if(sp->lo>=mylen) sp->hi=mylen-1;
if(sp->hi<=sp->lo) sp->hi=sp->lo+1;
if(sp->hi>mylen) sp->hi=mylen;
pldraw(p, p->b);
}
int pl_priscrollbar(Panel *, Point){
return PRI_SCROLLBAR;
}
void plinitscrollbar(Panel *v, int flags){
Scrollbar *sp;
sp=v->data;
v->flags=flags|LEAF;
v->pri=pl_priscrollbar;
v->state=UP;
v->draw=pl_drawscrollbar;
v->hit=pl_hitscrollbar;
v->type=pl_typescrollbar;
v->getsize=pl_getsizescrollbar;
v->childspace=pl_childspacescrollbar;
v->setscrollbar=pl_setscrollbarscrollbar;
switch(flags&PACK){
case PACKN:
case PACKS:
sp->dir=HORIZ;
sp->minsize=Pt(0, SBWID);
v->flags|=FILLX;
break;
case PACKE:
case PACKW:
sp->dir=VERT;
sp->minsize=Pt(SBWID, 0);
v->flags|=FILLY;
break;
}
sp->lo=0;
sp->hi=0;
v->kind="scrollbar";
}
Panel *plscrollbar(Panel *parent, int flags){
Panel *v;
v=pl_newpanel(parent, sizeof(Scrollbar));
plinitscrollbar(v, flags);
return v;
}
|