xref: /plan9/sys/src/cmd/abaco/rows.c (revision 7ab27030036b6c877a6f81728daeda263d1ca3cf)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <thread.h>
6 #include <cursor.h>
7 #include <mouse.h>
8 #include <keyboard.h>
9 #include <frame.h>
10 #include <plumb.h>
11 #include <html.h>
12 #include "dat.h"
13 #include "fns.h"
14 
15 void
rowinit(Row * row,Rectangle r)16 rowinit(Row *row, Rectangle r)
17 {
18 	Rectangle r1;
19 	Text *t;
20 
21 	draw(screen, r, display->white, nil, ZP);
22 	row->r = r;
23 	row->col = nil;
24 	row->ncol = 0;
25 	r1 = r;
26 	r1.max.y = r1.min.y + font->height;
27 	t = &row->tag;
28 	textinit(t, screen, r1, font, tagcols);
29 	t->what = Rowtag;
30 	t->row = row;
31 	t->w = nil;
32 	t->col = nil;
33 	r1.min.y = r1.max.y;
34 	r1.max.y += Border;
35 	draw(screen, r1, display->black, nil, ZP);
36 	textinsert(t, 0, L"Newcol Google Exit ", 19);
37 	textsetselect(t, t->rs.nr, t->rs.nr);
38 }
39 
40 Column*
rowadd(Row * row,Column * c,int x)41 rowadd(Row *row, Column *c, int x)
42 {
43 	Rectangle r, r1;
44 	Column *d;
45 	int i;
46 
47 	d = nil;
48 	r = row->r;
49 	r.min.y = row->tag.r.max.y+Border;
50 	if(x<r.min.x && row->ncol>0){	/*steal 40% of last column by default */
51 		d = row->col[row->ncol-1];
52 		x = d->r.min.x + 3*Dx(d->r)/5;
53 	}
54 	/* look for column we'll land on */
55 	for(i=0; i<row->ncol; i++){
56 		d = row->col[i];
57 		if(x < d->r.max.x)
58 			break;
59 	}
60 	if(row->ncol > 0){
61 		if(i < row->ncol)
62 			i++;	/* new column will go after d */
63 		r = d->r;
64 		if(Dx(r) < 100)
65 			return nil;
66 		draw(screen, r, display->white, nil, ZP);
67 		r1 = r;
68 		r1.max.x = min(x, r.max.x-50);
69 		if(Dx(r1) < 50)
70 			r1.max.x = r1.min.x+50;
71 		colresize(d, r1);
72 		r1.min.x = r1.max.x;
73 		r1.max.x = r1.min.x+Border;
74 		draw(screen, r1, display->black, nil, ZP);
75 		r.min.x = r1.max.x;
76 	}
77 	if(c == nil){
78 		c = emalloc(sizeof(Column));
79 		colinit(c, r);
80 	}else
81 		colresize(c, r);
82 	c->row = row;
83 	c->tag.row = row;
84 	row->col = realloc(row->col, (row->ncol+1)*sizeof(Column*));
85 	memmove(row->col+i+1, row->col+i, (row->ncol-i)*sizeof(Column*));
86 	row->col[i] = c;
87 	row->ncol++;
88 	clearmouse();
89 	return c;
90 }
91 
92 void
rowresize(Row * row,Rectangle r)93 rowresize(Row *row, Rectangle r)
94 {
95 	int i, dx, odx;
96 	Rectangle r1, r2;
97 	Column *c;
98 
99 	dx = Dx(r);
100 	odx = Dx(row->r);
101 	row->r = r;
102 	r1 = r;
103 	r1.max.y = r1.min.y + font->height;
104 	textresize(&row->tag, screen, r1);
105 	r1.min.y = r1.max.y;
106 	r1.max.y += Border;
107 	draw(screen, r1, display->black, nil, ZP);
108 	r.min.y = r1.max.y;
109 	r1 = r;
110 	r1.max.x = r1.min.x;
111 	for(i=0; i<row->ncol; i++){
112 		c = row->col[i];
113 		r1.min.x = r1.max.x;
114 		if(i == row->ncol-1)
115 			r1.max.x = r.max.x;
116 		else
117 			r1.max.x = r1.min.x+Dx(c->r)*dx/odx;
118 		if(i > 0){
119 			r2 = r1;
120 			r2.max.x = r2.min.x+Border;
121 			draw(screen, r2, display->black, nil, ZP);
122 			r1.min.x = r2.max.x;
123 		}
124 		colresize(c, r1);
125 	}
126 }
127 
128 void
rowdragcol(Row * row,Column * c,int)129 rowdragcol(Row *row, Column *c, int)
130 {
131 	Rectangle r;
132 	int i, b, x;
133 	Point p, op;
134 	Column *d;
135 
136 	clearmouse();
137 	setcursor(mousectl, &boxcursor);
138 	b = mouse->buttons;
139 	op = mouse->xy;
140 	while(mouse->buttons == b)
141 		readmouse(mousectl);
142 	setcursor(mousectl, nil);
143 	if(mouse->buttons){
144 		while(mouse->buttons)
145 			readmouse(mousectl);
146 		return;
147 	}
148 
149 	for(i=0; i<row->ncol; i++)
150 		if(row->col[i] == c)
151 			goto Found;
152 	error("can't find column");
153 
154   Found:
155 	if(i == 0)
156 		return;
157 	p = mouse->xy;
158 	if((abs(p.x-op.x)<5 && abs(p.y-op.y)<5))
159 		return;
160 	if((i>0 && p.x<row->col[i-1]->r.min.x) || (i<row->ncol-1 && p.x>c->r.max.x)){
161 		/* shuffle */
162 		x = c->r.min.x;
163 		rowclose(row, c, FALSE);
164 		if(rowadd(row, c, p.x) == nil)	/* whoops! */
165 		if(rowadd(row, c, x) == nil)		/* WHOOPS! */
166 		if(rowadd(row, c, -1)==nil){		/* shit! */
167 			rowclose(row, c, TRUE);
168 			return;
169 		}
170 		colmousebut(c);
171 		return;
172 	}
173 	d = row->col[i-1];
174 	if(p.x < d->r.min.x+80+Scrollsize)
175 		p.x = d->r.min.x+80+Scrollsize;
176 	if(p.x > c->r.max.x-80-Scrollsize)
177 		p.x = c->r.max.x-80-Scrollsize;
178 	r = d->r;
179 	r.max.x = c->r.max.x;
180 	draw(screen, r, display->white, nil, ZP);
181 	r.max.x = p.x;
182 	colresize(d, r);
183 	r = c->r;
184 	r.min.x = p.x;
185 	r.max.x = r.min.x;
186 	r.max.x += Border;
187 	draw(screen, r, display->black, nil, ZP);
188 	r.min.x = r.max.x;
189 	r.max.x = c->r.max.x;
190 	colresize(c, r);
191 	colmousebut(c);
192 }
193 
194 void
rowclose(Row * row,Column * c,int dofree)195 rowclose(Row *row, Column *c, int dofree)
196 {
197 	Rectangle r;
198 	int i;
199 
200 	for(i=0; i<row->ncol; i++)
201 		if(row->col[i] == c)
202 			goto Found;
203 	error("can't find column");
204   Found:
205 	r = c->r;
206 	if(dofree)
207 		colcloseall(c);
208 	memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*));
209 	row->ncol--;
210 	row->col = realloc(row->col, row->ncol*sizeof(Column*));
211 	if(row->ncol == 0){
212 		draw(screen, r, display->white, nil, ZP);
213 		return;
214 	}
215 	if(i == row->ncol){		/* extend last column right */
216 		c = row->col[i-1];
217 		r.min.x = c->r.min.x;
218 		r.max.x = row->r.max.x;
219 	}else{			/* extend next window left */
220 		c = row->col[i];
221 		r.max.x = c->r.max.x;
222 	}
223 	draw(screen, r, display->white, nil, ZP);
224 	colresize(c, r);
225 }
226 
227 Column*
rowwhichcol(Row * row,Point p)228 rowwhichcol(Row *row, Point p)
229 {
230 	int i;
231 	Column *c;
232 
233 	for(i=0; i<row->ncol; i++){
234 		c = row->col[i];
235 		if(ptinrect(p, c->r))
236 			return c;
237 	}
238 	return nil;
239 }
240 
241 Text*
rowwhich(Row * row,Point p,Rune r,int key)242 rowwhich(Row *row, Point p, Rune r, int key)
243 {
244 	Column *c;
245 
246 	if(ptinrect(p, row->tag.all))
247 		return &row->tag;
248 	c = rowwhichcol(row, p);
249 	if(c)
250 		return colwhich(c, p, r, key);
251 	return nil;
252 }
253