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 }