Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wbox.c
1
2 #include "WINGsP.h"
3
4 typedef struct {
5 WMView *view;
6 int minSize;
7 int maxSize;
8 int space;
9 unsigned expand:1;
10 unsigned fill:1;
11 unsigned end:1;
12 } SubviewItem;
13
14 typedef struct W_Box {
15 W_Class widgetClass;
16 W_View *view;
17
18 WMArray *subviews;
19
20 short borderWidth;
21
22 unsigned horizontal:1;
23 } Box;
24
25 #define DEFAULT_WIDTH 40
26 #define DEFAULT_HEIGHT 40
27
28 static void destroyBox(Box * bPtr);
29
30 static void handleEvents(XEvent * event, void *data);
31
32 static void didResize(struct W_ViewDelegate *, WMView *);
33
34 static W_ViewDelegate delegate = {
35 NULL,
36 NULL,
37 didResize,
38 NULL,
39 NULL
40 };
41
42 WMBox *WMCreateBox(WMWidget * parent)
43 {
44 Box *bPtr;
45
46 bPtr = wmalloc(sizeof(Box));
47 memset(bPtr, 0, sizeof(Box));
48
49 bPtr->widgetClass = WC_Box;
50
51 bPtr->view = W_CreateView(W_VIEW(parent));
52 if (!bPtr->view) {
53 wfree(bPtr);
54 return NULL;
55 }
56 bPtr->view->self = bPtr;
57
58 bPtr->view->delegate = &delegate;
59
60 bPtr->subviews = WMCreateArrayWithDestructor(2, wfree);
61
62 WMCreateEventHandler(bPtr->view, StructureNotifyMask, handleEvents, bPtr);
63
64 WMResizeWidget(bPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
65
66 return bPtr;
67 }
68
69 typedef struct {
70 WMBox *box;
71 int total;
72 int expands;
73 int x, y;
74 int xe, ye;
75 int w, h;
76 } BoxData;
77
78 static void computeExpansion(void *object, void *cdata)
79 {
80 SubviewItem *item = (SubviewItem *) object;
81 BoxData *eData = (BoxData *) cdata;
82
83 eData->total -= item->minSize;
84 eData->total -= item->space;
85 if (item->expand) {
86 eData->expands++;
87 }
88 }
89
90 static void doRearrange(void *object, void *cdata)
91 {
92 SubviewItem *item = (SubviewItem *) object;
93 BoxData *eData = (BoxData *) cdata;
94
95 if (eData->box->horizontal) {
96 eData->w = item->minSize;
97 if (item->expand)
98 eData->w += eData->total / eData->expands;
99 } else {
100 eData->h = item->minSize;
101 if (item->expand)
102 eData->h += eData->total / eData->expands;
103 }
104 if (!item->end) {
105 W_MoveView(item->view, eData->x, eData->y);
106 }
107 W_ResizeView(item->view, eData->w, eData->h);
108 if (eData->box->horizontal) {
109 if (item->end)
110 eData->xe -= eData->w + item->space;
111 else
112 eData->x += eData->w + item->space;
113 } else {
114 if (item->end)
115 eData->ye -= eData->h + item->space;
116 else
117 eData->y += eData->h + item->space;
118 }
119 if (item->end) {
120 W_MoveView(item->view, eData->xe, eData->ye);
121 }
122 }
123
124 static void rearrange(WMBox * box)
125 {
126 BoxData eData;
127
128 eData.box = box;
129 eData.x = eData.y = box->borderWidth;
130 eData.w = eData.h = 1;
131 eData.expands = 0;
132
133 if (box->horizontal) {
134 eData.ye = box->borderWidth;
135 eData.xe = WMWidgetWidth(box) - box->borderWidth;
136 eData.h = WMWidgetHeight(box) - 2 * box->borderWidth;
137 eData.total = WMWidgetWidth(box) - 2 * box->borderWidth;
138 } else {
139 eData.xe = box->borderWidth;
140 eData.ye = WMWidgetHeight(box) - box->borderWidth;
141 eData.w = WMWidgetWidth(box) - 2 * box->borderWidth;
142 eData.total = WMWidgetHeight(box) - 2 * box->borderWidth;
143 }
144
145 if (eData.w <= 0 || eData.h <= 0 || eData.total <= 0) {
146 return;
147 }
148
149 WMMapArray(box->subviews, computeExpansion, &eData);
150 WMMapArray(box->subviews, doRearrange, &eData);
151 }
152
153 void WMSetBoxBorderWidth(WMBox * box, unsigned width)
154 {
155 if (box->borderWidth != width) {
156 box->borderWidth = width;
157 rearrange(box);
158 }
159 }
160
161 void WMAddBoxSubview(WMBox * bPtr, WMView * view, Bool expand, Bool fill, int minSize, int maxSize, int space)
162 {
163 SubviewItem *subView;
164
165 subView = wmalloc(sizeof(SubviewItem));
166 subView->view = view;
167 subView->minSize = minSize;
168 subView->maxSize = maxSize;
169 subView->expand = expand;
170 subView->fill = fill;
171 subView->space = space;
172 subView->end = 0;
173
174 WMAddToArray(bPtr->subviews, subView);
175
176 rearrange(bPtr);
177 }
178
179 void WMAddBoxSubviewAtEnd(WMBox * bPtr, WMView * view, Bool expand, Bool fill, int minSize, int maxSize, int space)
180 {
181 SubviewItem *subView;
182
183 subView = wmalloc(sizeof(SubviewItem));
184 subView->view = view;
185 subView->minSize = minSize;
186 subView->maxSize = maxSize;
187 subView->expand = expand;
188 subView->fill = fill;
189 subView->space = space;
190 subView->end = 1;
191
192 WMAddToArray(bPtr->subviews, subView);
193
194 rearrange(bPtr);
195 }
196
197 static int matchView(void *item, void *cdata)
198 {
199 return (((SubviewItem *) item)->view == (WMView *) cdata);
200 }
201
202 void WMRemoveBoxSubview(WMBox * bPtr, WMView * view)
203 {
204 if (WMRemoveFromArrayMatching(bPtr->subviews, matchView, view)) {
205 rearrange(bPtr);
206 }
207 }
208
209 void WMSetBoxHorizontal(WMBox * box, Bool flag)
210 {
211 /* make sure flag is either 0 or 1 no matter what true value was passed */
212 flag = ((flag == 0) ? 0 : 1);
213 if (box->horizontal != flag) {
214 box->horizontal = flag;
215 rearrange(box);
216 }
217 }
218
219 static void destroyBox(Box * bPtr)
220 {
221 WMFreeArray(bPtr->subviews);
222 wfree(bPtr);
223 }
224
225 static void didResize(struct W_ViewDelegate *delegate, WMView * view)
226 {
227 rearrange(view->self);
228 }
229
230 static void handleEvents(XEvent * event, void *data)
231 {
232 Box *bPtr = (Box *) data;
233
234 CHECK_CLASS(data, WC_Box);
235
236 switch (event->type) {
237 case DestroyNotify:
238 destroyBox(bPtr);
239 break;
240
241 case ConfigureNotify:
242 rearrange(bPtr);
243 break;
244 }
245 }