fixed some stuffs
[wmaker-crm.git] / WINGs / wbox.c
blobea568acc6a52848df7ad91fee2419b20ac341dff
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 int topOffs;
27 int bottomOffs;
28 int leftOffs;
29 int rightOffs;
31 unsigned horizontal:1;
32 } Box;
35 #define DEFAULT_WIDTH 40
36 #define DEFAULT_HEIGHT 40
40 static void destroyBox(Box *bPtr);
42 static void handleEvents(XEvent *event, void *data);
44 static void didResize(struct W_ViewDelegate*, WMView*);
46 static W_ViewDelegate delegate = {
47 NULL,
48 NULL,
49 didResize,
50 NULL,
51 NULL
57 static void resizedParent(void *self, WMNotification *notif)
59 WMView *view = (WMView*)WMGetNotificationObject(notif);
60 WMSize size = WMGetViewSize(view);
61 WMBox *box = (WMBox*)self;
63 WMMoveWidget(box, box->leftOffs, box->topOffs);
64 WMResizeWidget(box, size.width - (box->leftOffs + box->rightOffs),
65 size.height - (box->topOffs + box->bottomOffs));
69 WMBox*
70 WMCreateBox(WMWidget *parent)
72 Box *bPtr;
74 bPtr = wmalloc(sizeof(Box));
75 memset(bPtr, 0, sizeof(Box));
77 bPtr->widgetClass = WC_Box;
79 bPtr->view = W_CreateView(W_VIEW(parent));
80 if (!bPtr->view) {
81 wfree(bPtr);
82 return NULL;
84 bPtr->view->self = bPtr;
86 bPtr->view->delegate = &delegate;
88 WMCreateEventHandler(bPtr->view, StructureNotifyMask,
89 handleEvents, bPtr);
91 WMResizeWidget(bPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
93 bPtr->subviews = NULL;
94 bPtr->subviewCount = 0;
96 return bPtr;
100 static void
101 rearrange(WMBox *box)
103 int i;
104 int x, y;
105 int xe, ye;
106 int w = 1, h = 1;
107 int total;
108 int expands = 0;
110 x = box->borderWidth;
111 y = box->borderWidth;
113 if (box->horizontal) {
114 ye = box->borderWidth;
115 xe = WMWidgetWidth(box) - box->borderWidth;
116 h = WMWidgetHeight(box) - 2 * box->borderWidth;
117 total = WMWidgetWidth(box) - 2 * box->borderWidth;
118 } else {
119 xe = box->borderWidth;
120 ye = WMWidgetHeight(box) - box->borderWidth;
121 w = WMWidgetWidth(box) - 2 * box->borderWidth;
122 total = WMWidgetHeight(box) - 2 * box->borderWidth;
125 if (w <= 0 || h <= 0 || total <= 0) {
126 return;
129 for (i = 0; i < box->subviewCount; i++) {
130 total -= box->subviews[i].minSize;
131 total -= box->subviews[i].space;
132 if (box->subviews[i].expand) {
133 expands++;
137 for (i = 0; i < box->subviewCount; i++) {
138 if (box->horizontal) {
139 w = box->subviews[i].minSize;
140 if (box->subviews[i].expand)
141 w += total/expands;
142 } else {
143 h = box->subviews[i].minSize;
144 if (box->subviews[i].expand)
145 h += total/expands;
147 if (!box->subviews[i].end) {
148 W_MoveView(box->subviews[i].view, x, y);
150 W_ResizeView(box->subviews[i].view, w, h);
151 if (box->horizontal) {
152 if (box->subviews[i].end)
153 xe -= w + box->subviews[i].space;
154 else
155 x += w + box->subviews[i].space;
156 } else {
157 if (box->subviews[i].end)
158 ye -= h + box->subviews[i].space;
159 else
160 y += h + box->subviews[i].space;
162 if (box->subviews[i].end) {
163 W_MoveView(box->subviews[i].view, xe, ye);
169 void
170 WMSetBoxBorderWidth(WMBox *box, unsigned width)
172 box->borderWidth = width;
174 rearrange(box);
178 void
179 WMAddBoxSubview(WMBox *bPtr, WMView *view, Bool expand, Bool fill,
180 int minSize, int maxSize, int space)
182 int i = bPtr->subviewCount;
184 bPtr->subviewCount++;
185 if (!bPtr->subviews)
186 bPtr->subviews = wmalloc(sizeof(SubviewItem));
187 else
188 bPtr->subviews = wrealloc(bPtr->subviews,
189 bPtr->subviewCount*sizeof(SubviewItem));
190 bPtr->subviews[i].view = view;
191 bPtr->subviews[i].minSize = minSize;
192 bPtr->subviews[i].maxSize = maxSize;
193 bPtr->subviews[i].expand = expand;
194 bPtr->subviews[i].fill = fill;
195 bPtr->subviews[i].space = space;
196 bPtr->subviews[i].end = 0;
198 rearrange(bPtr);
203 void
204 WMAddBoxSubviewAtEnd(WMBox *bPtr, WMView *view, Bool expand, Bool fill,
205 int minSize, int maxSize, int space)
207 int i = bPtr->subviewCount;
209 bPtr->subviewCount++;
210 if (!bPtr->subviews)
211 bPtr->subviews = wmalloc(sizeof(SubviewItem));
212 else
213 bPtr->subviews = wrealloc(bPtr->subviews,
214 bPtr->subviewCount*sizeof(SubviewItem));
215 bPtr->subviews[i].view = view;
216 bPtr->subviews[i].minSize = minSize;
217 bPtr->subviews[i].maxSize = maxSize;
218 bPtr->subviews[i].expand = expand;
219 bPtr->subviews[i].fill = fill;
220 bPtr->subviews[i].space = space;
221 bPtr->subviews[i].end = 1;
223 rearrange(bPtr);
227 void
228 WMRemoveBoxSubview(WMBox *bPtr, WMView *view)
230 int i;
232 for (i = 0; i < bPtr->subviewCount; i++) {
233 if (bPtr->subviews[i].view == view) {
234 memmove(&bPtr->subviews[i], &bPtr->subviews[i+1],
235 (bPtr->subviewCount - i - 1) * sizeof(void*));
236 bPtr->subviewCount--;
237 break;
240 rearrange(bPtr);
244 void
245 WMSetBoxHorizontal(WMBox *box, Bool flag)
247 box->horizontal = flag;
248 rearrange(box);
252 void
253 WMSetBoxExpandsToParent(WMBox *box, int topOffs, int bottomOffs,
254 int leftOffs, int rightOffs)
256 WMSize size = W_VIEW(box)->parent->size;
258 box->topOffs = topOffs;
259 box->bottomOffs = bottomOffs;
260 box->leftOffs = leftOffs;
261 box->rightOffs = rightOffs;
263 WMAddNotificationObserver(resizedParent, box,
264 WMViewSizeDidChangeNotification,
265 W_VIEW(box)->parent);
266 WMSetViewNotifySizeChanges(W_VIEW(box)->parent, True);
268 WMMoveWidget(box, leftOffs, topOffs);
269 WMResizeWidget(box, size.width - (leftOffs + rightOffs),
270 size.height - (topOffs + bottomOffs));
274 static void
275 destroyBox(Box *bPtr)
277 WMRemoveNotificationObserver(bPtr);
278 wfree(bPtr);
282 static void
283 didResize(struct W_ViewDelegate *delegate, WMView *view)
285 rearrange(view->self);
289 static void
290 handleEvents(XEvent *event, void *data)
292 Box *bPtr = (Box*)data;
294 CHECK_CLASS(data, WC_Box);
296 switch (event->type) {
297 case DestroyNotify:
298 destroyBox(bPtr);
299 break;
301 case ConfigureNotify:
302 rearrange(bPtr);
303 break;