~amavect/makeu

makeu/guipart.c -rw-r--r-- 3.7 KiB
8a2a5c28amavect revise error exiting, allocation errors 1 year, 3 months ago
                                                                                
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* Amavect! */
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <keyboard.h>
#include <elementile.h>

/*
 * Calculate minimum size by the minimum sizes of the children,
 * the division type, and the division width.
 */
Point
guipartinit(Elementile *e)
{
	Guipart *gp;
	Point p;
	
	gp = e->aux;
	gp->sel = nil;
	gp->ltmin = gp->lt->init(gp->lt);
	gp->rbmin = gp->rb->init(gp->rb);
	if(gp->vh == Hdiv){
		p.x = gp->ltmin.x > gp->rbmin.x ? gp->ltmin.x : gp->rbmin.x;
		p.y = gp->ltmin.y + gp->rbmin.y + 2*gp->w;
	}else{
		p.x = gp->ltmin.x + gp->rbmin.x + 2*gp->w;
		p.y = gp->ltmin.y > gp->rbmin.y ? gp->ltmin.y : gp->rbmin.y;
	}
	return p;
}

/*
 * Resize while enforcing the minimum size.
 * Divide rectangle based on horizontal or vertical division.
 * Set lt size by setting max. If lt is too small, increase max.
 * Set rb size by setting min. If rb is too small, increase max.
 * Recurse into subelements.
 */
void
guipartresize(Elementile *e, Rectangle rect)
{
	Guipart *gp;
	int w;
	
	gp = e->aux;
	w = gp->w;
	
	gp->ltrect.min = rect.min;
	gp->rbrect.max = rect.max;
	
	if(gp->vh == Hdiv){
		gp->ltrect.max.x = rect.max.x;
		gp->rbrect.min.x = rect.min.x;
		/* add 0.5 and cast for int rounding */
		gp->ltrect.max.y = (int)(Dy(rect) * gp->d + 0.5) + rect.min.y - w;
		if(Dy(rect) - Dy(gp->ltrect) < gp->rbmin.y)
			gp->ltrect.max.y = rect.max.y - gp->rbmin.y - 2 * w;
		if(Dy(gp->ltrect) < gp->ltmin.y)
			gp->ltrect.max.y = gp->ltrect.min.y + gp->ltmin.y;
		gp->rbrect.min.y = gp->ltrect.max.y + 2 * w;
		if(Dy(gp->rbrect) < gp->rbmin.y)
			gp->rbrect.max.y = gp->rbrect.min.y + gp->rbmin.y;
	}else{
		gp->ltrect.max.y = rect.max.y;
		gp->rbrect.min.y = rect.min.y;
		/* add 0.5 and cast for int rounding */
		gp->ltrect.max.x = (int)(Dx(rect) * gp->d + 0.5) + rect.min.x - w;
		if(Dx(rect) - Dx(gp->ltrect) < gp->rbmin.x)
			gp->ltrect.max.x = rect.max.x - gp->rbmin.x - 2 * w;
		if(Dx(gp->ltrect) < gp->ltmin.x)
			gp->ltrect.max.x = gp->ltrect.min.x + gp->ltmin.x;
		gp->rbrect.min.x = gp->ltrect.max.x + 2 * w;
		if(Dx(gp->rbrect) < gp->rbmin.x)
			gp->rbrect.max.x = gp->rbrect.min.x + gp->rbmin.x;
	}
	
	gp->lt->resize(gp->lt, gp->ltrect);
	gp->rb->resize(gp->rb, gp->rbrect);
}

/*
 * Update all elements.
 */
int
guipartupdate(Elementile *e)
{
	Guipart *gp;
	
	gp = e->aux;
	gp->lt->update(gp->lt);
	gp->rb->update(gp->rb);
	
	return 1;
}

/*
 * The mouse input may be routed to the child Elementile, depending on some state.
 * If currently focused Elementile is not nil, the mouse is passed to it.
 * Then, if no button is pressed, search for a new Elementile.
 * If a different Elementile is found, also send the mouse to it.
 * If no Elementile is found, the selected Elementile becomes nil.
 * 
 * Summary of cases for mouse input to be sent to a member Guielem:
 * mouse entry, exit, movement inside, button presses (anywhere), button releases (anywhere).
 */
int
guipartmouse(Elementile *e, Mouse m)
{
	Guipart *gp;
	int v;
	
	gp = e->aux;
	v = 0;
	
	if(gp->sel != nil)
		v = gp->sel->mouse(gp->sel, m);
	
	if(m.buttons == 0){
		if(ptinrect(m.xy, gp->ltrect)){
			if(gp->sel != gp->lt){
				gp->sel = gp->lt;
				v |= gp->sel->mouse(gp->sel, m);
			}
		}else if(ptinrect(m.xy, gp->rbrect)){
			if(gp->sel != gp->rb){
				gp->sel = gp->rb;
				v |= gp->sel->mouse(gp->sel, m);
			}
		}else{
			gp->sel = nil;
		}
	}
	
	return v;
}

/* 
 * Just send to the currently selected element.
 */
int
guipartkeyboard(Elementile *e, Rune r)
{
	Guipart *gp;
	int v;
	
	gp = e->aux;
	v = 0;
	
	if(gp->sel != nil)
		v = gp->sel->keyboard(gp->sel, r);
	
	return v;
}

void
guipartfree(Elementile *e)
{
	Guipart *gp;
	
	gp = e->aux;
	
	gp->lt->free(gp->lt);
	gp->rb->free(gp->rb);
}