fixed various bugs
[wmaker-crm.git] / WINGs / wbox.c
blob42757603d1ce1668dab5c8f23a5b92edae1ac958
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
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 static void resizedParent(void *self, WMNotification *notif)
53 WMView *view = (WMView*)WMGetNotificationObject(notif);
54 WMSize size = WMGetViewSize(view);
56 WMResizeWidget((WMWidget*)self, size.width, size.height);
60 WMBox*
61 WMCreateBox(WMWidget *parent)
63 Box *bPtr;
65 bPtr = wmalloc(sizeof(Box));
66 memset(bPtr, 0, sizeof(Box));
68 bPtr->widgetClass = WC_Box;
70 bPtr->view = W_CreateView(W_VIEW(parent));
71 if (!bPtr->view) {
72 wfree(bPtr);
73 return NULL;
75 bPtr->view->self = bPtr;
77 bPtr->view->delegate = &delegate;
79 WMCreateEventHandler(bPtr->view, StructureNotifyMask,
80 handleEvents, bPtr);
82 WMResizeWidget(bPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
84 bPtr->subviews = NULL;
85 bPtr->subviewCount = 0;
87 return bPtr;
91 static void
92 rearrange(WMBox *box)
94 int i;
95 int x, y;
96 int xe, ye;
97 int w = 1, h = 1;
98 int total;
99 int expands = 0;
101 x = box->borderWidth;
102 y = box->borderWidth;
104 if (box->horizontal) {
105 ye = box->borderWidth;
106 xe = WMWidgetWidth(box) - box->borderWidth;
107 h = WMWidgetHeight(box) - 2 * box->borderWidth;
108 total = WMWidgetWidth(box) - 2 * box->borderWidth;
109 } else {
110 xe = box->borderWidth;
111 ye = WMWidgetHeight(box) - box->borderWidth;
112 w = WMWidgetWidth(box) - 2 * box->borderWidth;
113 total = WMWidgetHeight(box) - 2 * box->borderWidth;
116 if (w <= 0 || h <= 0 || total <= 0) {
117 return;
120 for (i = 0; i < box->subviewCount; i++) {
121 total -= box->subviews[i].minSize;
122 total -= box->subviews[i].space;
123 if (box->subviews[i].expand) {
124 expands++;
128 for (i = 0; i < box->subviewCount; i++) {
129 if (box->horizontal) {
130 w = box->subviews[i].minSize;
131 if (box->subviews[i].expand)
132 w += total/expands;
133 } else {
134 h = box->subviews[i].minSize;
135 if (box->subviews[i].expand)
136 h += total/expands;
138 if (!box->subviews[i].end) {
139 W_MoveView(box->subviews[i].view, x, y);
141 W_ResizeView(box->subviews[i].view, w, h);
142 if (box->horizontal) {
143 if (box->subviews[i].end)
144 xe -= w + box->subviews[i].space;
145 else
146 x += w + box->subviews[i].space;
147 } else {
148 if (box->subviews[i].end)
149 ye -= h + box->subviews[i].space;
150 else
151 y += h + box->subviews[i].space;
153 if (box->subviews[i].end) {
154 W_MoveView(box->subviews[i].view, xe, ye);
160 void
161 WMSetBoxBorderWidth(WMBox *box, unsigned width)
163 box->borderWidth = width;
165 rearrange(box);
169 void
170 WMAddBoxSubview(WMBox *bPtr, WMView *view, Bool expand, Bool fill,
171 int minSize, int maxSize, int space)
173 int i = bPtr->subviewCount;
175 bPtr->subviewCount++;
176 if (!bPtr->subviews)
177 bPtr->subviews = wmalloc(sizeof(SubviewItem));
178 else
179 bPtr->subviews = wrealloc(bPtr->subviews,
180 bPtr->subviewCount*sizeof(SubviewItem));
181 bPtr->subviews[i].view = view;
182 bPtr->subviews[i].minSize = minSize;
183 bPtr->subviews[i].maxSize = maxSize;
184 bPtr->subviews[i].expand = expand;
185 bPtr->subviews[i].fill = fill;
186 bPtr->subviews[i].space = space;
187 bPtr->subviews[i].end = 0;
189 rearrange(bPtr);
194 void
195 WMAddBoxSubviewAtEnd(WMBox *bPtr, WMView *view, Bool expand, Bool fill,
196 int minSize, int maxSize, int space)
198 int i = bPtr->subviewCount;
200 bPtr->subviewCount++;
201 if (!bPtr->subviews)
202 bPtr->subviews = wmalloc(sizeof(SubviewItem));
203 else
204 bPtr->subviews = wrealloc(bPtr->subviews,
205 bPtr->subviewCount*sizeof(SubviewItem));
206 bPtr->subviews[i].view = view;
207 bPtr->subviews[i].minSize = minSize;
208 bPtr->subviews[i].maxSize = maxSize;
209 bPtr->subviews[i].expand = expand;
210 bPtr->subviews[i].fill = fill;
211 bPtr->subviews[i].space = space;
212 bPtr->subviews[i].end = 1;
214 rearrange(bPtr);
218 void
219 WMSetBoxHorizontal(WMBox *box, Bool flag)
221 box->horizontal = flag;
222 rearrange(box);
226 void
227 WMSetBoxExpandsToParent(WMBox *box)
229 WMAddNotificationObserver(resizedParent, box,
230 WMViewSizeDidChangeNotification,
231 W_VIEW(box)->parent);
232 WMSetViewNotifySizeChanges(W_VIEW(box)->parent, True);
233 WMResizeWidget(box, W_VIEW(box)->parent->size.width,
234 W_VIEW(box)->parent->size.height);
238 static void
239 destroyBox(Box *bPtr)
241 wfree(bPtr);
245 static void
246 didResize(struct W_ViewDelegate *delegate, WMView *view)
248 rearrange(view->self);
251 static void
252 handleEvents(XEvent *event, void *data)
254 Box *bPtr = (Box*)data;
256 CHECK_CLASS(data, WC_Box);
258 switch (event->type) {
259 case DestroyNotify:
260 destroyBox(bPtr);
261 break;
263 case ConfigureNotify:
264 rearrange(bPtr);
265 break;