small update to display if xinerama is supported in the configure summary. nicer...
[wmaker-crm.git] / WINGs / wbox.c
blob00742a3c36b59696b17deb0d95c66f9b0fe474af
3 #include "WINGsP.h"
6 typedef struct {
7 WMView *view;
8 int minSize;
9 int maxSize;
10 int space;
11 unsigned expand:1;
12 unsigned fill:1;
13 unsigned end:1;
14 } SubviewItem;
17 typedef struct W_Box {
18 W_Class widgetClass;
19 W_View *view;
21 WMArray *subviews;
23 short borderWidth;
25 unsigned horizontal:1;
26 } Box;
29 #define DEFAULT_WIDTH 40
30 #define DEFAULT_HEIGHT 40
34 static void destroyBox(Box *bPtr);
36 static void handleEvents(XEvent *event, void *data);
38 static void didResize(struct W_ViewDelegate*, WMView*);
40 static W_ViewDelegate delegate = {
41 NULL,
42 NULL,
43 didResize,
44 NULL,
45 NULL
51 WMBox*
52 WMCreateBox(WMWidget *parent)
54 Box *bPtr;
56 bPtr = wmalloc(sizeof(Box));
57 memset(bPtr, 0, sizeof(Box));
59 bPtr->widgetClass = WC_Box;
61 bPtr->view = W_CreateView(W_VIEW(parent));
62 if (!bPtr->view) {
63 wfree(bPtr);
64 return NULL;
66 bPtr->view->self = bPtr;
68 bPtr->view->delegate = &delegate;
70 bPtr->subviews = WMCreateArrayWithDestructor(2, wfree);
72 WMCreateEventHandler(bPtr->view, StructureNotifyMask,
73 handleEvents, bPtr);
75 WMResizeWidget(bPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
77 return bPtr;
81 typedef struct {
82 WMBox *box;
83 int total;
84 int expands;
85 int x, y;
86 int xe, ye;
87 int w, h;
88 } BoxData;
91 static void
92 computeExpansion(void *object, void *cdata)
94 SubviewItem *item = (SubviewItem*)object;
95 BoxData *eData = (BoxData*)cdata;
97 eData->total -= item->minSize;
98 eData->total -= item->space;
99 if (item->expand) {
100 eData->expands++;
105 static void
106 doRearrange(void *object, void *cdata)
108 SubviewItem *item = (SubviewItem*)object;
109 BoxData *eData = (BoxData*)cdata;
111 if (eData->box->horizontal) {
112 eData->w = item->minSize;
113 if (item->expand)
114 eData->w += eData->total/eData->expands;
115 } else {
116 eData->h = item->minSize;
117 if (item->expand)
118 eData->h += eData->total/eData->expands;
120 if (!item->end) {
121 W_MoveView(item->view, eData->x, eData->y);
123 W_ResizeView(item->view, eData->w, eData->h);
124 if (eData->box->horizontal) {
125 if (item->end)
126 eData->xe -= eData->w + item->space;
127 else
128 eData->x += eData->w + item->space;
129 } else {
130 if (item->end)
131 eData->ye -= eData->h + item->space;
132 else
133 eData->y += eData->h + item->space;
135 if (item->end) {
136 W_MoveView(item->view, eData->xe, eData->ye);
141 static void
142 rearrange(WMBox *box)
144 BoxData eData;
146 eData.box = box;
147 eData.x = eData.y = box->borderWidth;
148 eData.w = eData.h = 1;
149 eData.expands = 0;
151 if (box->horizontal) {
152 eData.ye = box->borderWidth;
153 eData.xe = WMWidgetWidth(box) - box->borderWidth;
154 eData.h = WMWidgetHeight(box) - 2 * box->borderWidth;
155 eData.total = WMWidgetWidth(box) - 2 * box->borderWidth;
156 } else {
157 eData.xe = box->borderWidth;
158 eData.ye = WMWidgetHeight(box) - box->borderWidth;
159 eData.w = WMWidgetWidth(box) - 2 * box->borderWidth;
160 eData.total = WMWidgetHeight(box) - 2 * box->borderWidth;
163 if (eData.w <= 0 || eData.h <= 0 || eData.total <= 0) {
164 return;
167 WMMapArray(box->subviews, computeExpansion, &eData);
168 WMMapArray(box->subviews, doRearrange, &eData);
172 void
173 WMSetBoxBorderWidth(WMBox *box, unsigned width)
175 if (box->borderWidth != width) {
176 box->borderWidth = width;
177 rearrange(box);
182 void
183 WMAddBoxSubview(WMBox *bPtr, WMView *view, Bool expand, Bool fill,
184 int minSize, int maxSize, int space)
186 SubviewItem *subView;
188 subView = wmalloc(sizeof(SubviewItem));
189 subView->view = view;
190 subView->minSize = minSize;
191 subView->maxSize = maxSize;
192 subView->expand = expand;
193 subView->fill = fill;
194 subView->space = space;
195 subView->end = 0;
197 WMAddToArray(bPtr->subviews, subView);
199 rearrange(bPtr);
204 void
205 WMAddBoxSubviewAtEnd(WMBox *bPtr, WMView *view, Bool expand, Bool fill,
206 int minSize, int maxSize, int space)
208 SubviewItem *subView;
210 subView = wmalloc(sizeof(SubviewItem));
211 subView->view = view;
212 subView->minSize = minSize;
213 subView->maxSize = maxSize;
214 subView->expand = expand;
215 subView->fill = fill;
216 subView->space = space;
217 subView->end = 1;
219 WMAddToArray(bPtr->subviews, subView);
221 rearrange(bPtr);
225 static int
226 matchView(void *item, void *cdata)
228 return (((SubviewItem*)item)->view == (WMView*)cdata);
232 void
233 WMRemoveBoxSubview(WMBox *bPtr, WMView *view)
235 if (WMRemoveFromArrayMatching(bPtr->subviews, matchView, view)) {
236 rearrange(bPtr);
241 void
242 WMSetBoxHorizontal(WMBox *box, Bool flag)
244 /* make sure flag is either 0 or 1 no matter what true value was passed */
245 flag = ((flag==0) ? 0 : 1);
246 if (box->horizontal != flag) {
247 box->horizontal = flag;
248 rearrange(box);
253 static void
254 destroyBox(Box *bPtr)
256 WMFreeArray(bPtr->subviews);
257 wfree(bPtr);
261 static void
262 didResize(struct W_ViewDelegate *delegate, WMView *view)
264 rearrange(view->self);
268 static void
269 handleEvents(XEvent *event, void *data)
271 Box *bPtr = (Box*)data;
273 CHECK_CLASS(data, WC_Box);
275 switch (event->type) {
276 case DestroyNotify:
277 destroyBox(bPtr);
278 break;
280 case ConfigureNotify:
281 rearrange(bPtr);
282 break;