A few miscelaneous fixes
[wmaker-crm.git] / WINGs / wbox.c
blobf11de212216f65ba7aa7e86c4eb09d55e2084d19
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 SubviewItem *subviews;
22 int subviewCount;
24 short borderWidth;
26 unsigned horizontal:1;
27 } Box;
30 #define DEFAULT_WIDTH 40
31 #define DEFAULT_HEIGHT 40
35 static void destroyBox(Box *bPtr);
37 static void handleEvents(XEvent *event, void *data);
39 static void didResize(struct W_ViewDelegate*, WMView*);
41 static W_ViewDelegate delegate = {
42 NULL,
43 NULL,
44 didResize,
45 NULL,
46 NULL
52 WMBox*
53 WMCreateBox(WMWidget *parent)
55 Box *bPtr;
57 bPtr = wmalloc(sizeof(Box));
58 memset(bPtr, 0, sizeof(Box));
60 bPtr->widgetClass = WC_Box;
62 bPtr->view = W_CreateView(W_VIEW(parent));
63 if (!bPtr->view) {
64 wfree(bPtr);
65 return NULL;
67 bPtr->view->self = bPtr;
69 bPtr->view->delegate = &delegate;
71 WMCreateEventHandler(bPtr->view, StructureNotifyMask,
72 handleEvents, bPtr);
74 WMResizeWidget(bPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
76 bPtr->subviews = NULL;
77 bPtr->subviewCount = 0;
79 return bPtr;
83 static void
84 rearrange(WMBox *box)
86 int i;
87 int x, y;
88 int xe, ye;
89 int w = 1, h = 1;
90 int total;
91 int expands = 0;
93 x = box->borderWidth;
94 y = box->borderWidth;
96 if (box->horizontal) {
97 ye = box->borderWidth;
98 xe = WMWidgetWidth(box) - box->borderWidth;
99 h = WMWidgetHeight(box) - 2 * box->borderWidth;
100 total = WMWidgetWidth(box) - 2 * box->borderWidth;
101 } else {
102 xe = box->borderWidth;
103 ye = WMWidgetHeight(box) - box->borderWidth;
104 w = WMWidgetWidth(box) - 2 * box->borderWidth;
105 total = WMWidgetHeight(box) - 2 * box->borderWidth;
108 if (w <= 0 || h <= 0 || total <= 0) {
109 return;
112 for (i = 0; i < box->subviewCount; i++) {
113 total -= box->subviews[i].minSize;
114 total -= box->subviews[i].space;
115 if (box->subviews[i].expand) {
116 expands++;
120 for (i = 0; i < box->subviewCount; i++) {
121 if (box->horizontal) {
122 w = box->subviews[i].minSize;
123 if (box->subviews[i].expand)
124 w += total/expands;
125 } else {
126 h = box->subviews[i].minSize;
127 if (box->subviews[i].expand)
128 h += total/expands;
130 if (!box->subviews[i].end) {
131 W_MoveView(box->subviews[i].view, x, y);
133 W_ResizeView(box->subviews[i].view, w, h);
134 if (box->horizontal) {
135 if (box->subviews[i].end)
136 xe -= w + box->subviews[i].space;
137 else
138 x += w + box->subviews[i].space;
139 } else {
140 if (box->subviews[i].end)
141 ye -= h + box->subviews[i].space;
142 else
143 y += h + box->subviews[i].space;
145 if (box->subviews[i].end) {
146 W_MoveView(box->subviews[i].view, xe, ye);
152 void
153 WMSetBoxBorderWidth(WMBox *box, unsigned width)
155 if (box->borderWidth != width) {
156 box->borderWidth = width;
157 rearrange(box);
162 void
163 WMAddBoxSubview(WMBox *bPtr, WMView *view, Bool expand, Bool fill,
164 int minSize, int maxSize, int space)
166 int i = bPtr->subviewCount;
168 bPtr->subviewCount++;
169 if (!bPtr->subviews)
170 bPtr->subviews = wmalloc(sizeof(SubviewItem));
171 else
172 bPtr->subviews = wrealloc(bPtr->subviews,
173 bPtr->subviewCount*sizeof(SubviewItem));
174 bPtr->subviews[i].view = view;
175 bPtr->subviews[i].minSize = minSize;
176 bPtr->subviews[i].maxSize = maxSize;
177 bPtr->subviews[i].expand = expand;
178 bPtr->subviews[i].fill = fill;
179 bPtr->subviews[i].space = space;
180 bPtr->subviews[i].end = 0;
182 rearrange(bPtr);
187 void
188 WMAddBoxSubviewAtEnd(WMBox *bPtr, WMView *view, Bool expand, Bool fill,
189 int minSize, int maxSize, int space)
191 int i = bPtr->subviewCount;
193 bPtr->subviewCount++;
194 if (!bPtr->subviews)
195 bPtr->subviews = wmalloc(sizeof(SubviewItem));
196 else
197 bPtr->subviews = wrealloc(bPtr->subviews,
198 bPtr->subviewCount*sizeof(SubviewItem));
199 bPtr->subviews[i].view = view;
200 bPtr->subviews[i].minSize = minSize;
201 bPtr->subviews[i].maxSize = maxSize;
202 bPtr->subviews[i].expand = expand;
203 bPtr->subviews[i].fill = fill;
204 bPtr->subviews[i].space = space;
205 bPtr->subviews[i].end = 1;
207 rearrange(bPtr);
211 void
212 WMRemoveBoxSubview(WMBox *bPtr, WMView *view)
214 int i;
216 for (i = 0; i < bPtr->subviewCount; i++) {
217 if (bPtr->subviews[i].view == view) {
218 memmove(&bPtr->subviews[i], &bPtr->subviews[i+1],
219 (bPtr->subviewCount - i - 1) * sizeof(void*));
220 bPtr->subviewCount--;
221 break;
224 rearrange(bPtr);
228 void
229 WMSetBoxHorizontal(WMBox *box, Bool flag)
231 /* make sure flag is either 0 or 1 no matter what true value was passed */
232 flag = ((flag==0) ? 0 : 1);
233 if (box->horizontal != flag) {
234 box->horizontal = flag;
235 rearrange(box);
240 static void
241 destroyBox(Box *bPtr)
243 WMRemoveNotificationObserver(bPtr);
244 wfree(bPtr);
248 static void
249 didResize(struct W_ViewDelegate *delegate, WMView *view)
251 rearrange(view->self);
255 static void
256 handleEvents(XEvent *event, void *data)
258 Box *bPtr = (Box*)data;
260 CHECK_CLASS(data, WC_Box);
262 switch (event->type) {
263 case DestroyNotify:
264 destroyBox(bPtr);
265 break;
267 case ConfigureNotify:
268 rearrange(bPtr);
269 break;