Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / libs / muimaster / classes / scrollgroup.c
blobf1e61fe808ae4530a4341af7c5fa703a95dd95e7
1 /*
2 Copyright © 2002-2006, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define MUIMASTER_YES_INLINE_STDARG
8 #include <exec/memory.h>
9 #include <intuition/icclass.h>
10 #include <intuition/gadgetclass.h>
11 #include <clib/alib_protos.h>
12 #include <proto/exec.h>
13 #include <proto/intuition.h>
14 #include <proto/utility.h>
15 #include <proto/muimaster.h>
17 /* #define MYDEBUG 1 */
18 #include "debug.h"
19 #include "mui.h"
20 #include "muimaster_intern.h"
21 #include "support.h"
22 #include "support_classes.h"
23 #include "scrollgroup_private.h"
25 extern struct Library *MUIMasterBase;
28 AROS_UFH3(ULONG,Scrollgroup_Layout_Function,
29 AROS_UFHA(struct Hook *, hook, A0),
30 AROS_UFHA(Object *, obj, A2),
31 AROS_UFHA(struct MUI_LayoutMsg *, lm, A1))
33 AROS_USERFUNC_INIT
35 struct Scrollgroup_DATA *data = (struct Scrollgroup_DATA *)hook->h_Data;
36 switch (lm->lm_Type)
38 case MUILM_MINMAX:
40 /* Calulate the minmax dimension of the group,
41 ** We only have a fixed number of children, so we need no NextObject()
44 if (data->usewinborder)
46 lm->lm_MinMax.MinWidth = _minwidth(data->contents);
47 lm->lm_MinMax.MinHeight = _minheight(data->contents);
48 lm->lm_MinMax.DefWidth = _defwidth(data->contents);
49 lm->lm_MinMax.DefHeight = _defheight(data->contents);
50 lm->lm_MinMax.MaxWidth = _maxwidth(data->contents);
51 lm->lm_MinMax.MaxHeight = _maxheight(data->contents);
54 else
56 WORD maxxxxwidth = 0;
57 WORD maxxxxheight = 0;
59 maxxxxwidth = _minwidth(data->contents);
60 if (_minwidth(data->horiz) > maxxxxwidth) maxxxxwidth = _minwidth(data->horiz);
61 maxxxxwidth += _minwidth(data->vert);
62 lm->lm_MinMax.MinWidth = maxxxxwidth;
64 maxxxxheight = _minheight(data->contents);
65 if (_minheight(data->vert) > maxxxxheight) maxxxxheight = _minheight(data->vert);
66 maxxxxheight += _minheight(data->horiz);
67 lm->lm_MinMax.MinHeight = maxxxxheight;
69 maxxxxwidth = _defwidth(data->contents);
70 if (_defwidth(data->horiz) > maxxxxwidth) maxxxxwidth = _defwidth(data->horiz);
71 if (maxxxxwidth < lm->lm_MinMax.MinWidth) maxxxxwidth = lm->lm_MinMax.MinWidth;
72 lm->lm_MinMax.DefWidth = maxxxxwidth;
74 maxxxxheight = _defheight(data->contents);
75 if (_defheight(data->vert) > maxxxxheight) maxxxxheight = _defheight(data->vert);
76 if (maxxxxheight < lm->lm_MinMax.MinHeight) maxxxxheight = lm->lm_MinMax.MinHeight;
77 lm->lm_MinMax.DefHeight = maxxxxheight;
79 lm->lm_MinMax.MaxWidth = MUI_MAXMAX;
80 lm->lm_MinMax.MaxHeight = MUI_MAXMAX;
83 //kprintf("scrollgroup minmax: min %d x %d def %d x %d\n",
84 // lm->lm_MinMax.MinWidth, lm->lm_MinMax.MinHeight,
85 // lm->lm_MinMax.DefWidth, lm->lm_MinMax.DefHeight);
87 //kprintf("contents minmax: min %d x %d def %d x %d\n",
88 // _minwidth(data->contents), _minheight(data->contents),
89 // _defwidth(data->contents), _defheight(data->contents));
91 return 0;
94 case MUILM_LAYOUT:
96 /* Now place the objects between (0,0,lm->lm_Layout.Width-1,lm->lm_Layout.Height-1)
99 LONG virt_width;
100 LONG virt_height;
101 LONG virt_minwidth;
102 LONG virt_minheight;
103 LONG virt_maxwidth;
104 LONG virt_maxheight;
105 LONG vert_width = _minwidth(data->vert);
106 LONG horiz_height = _minheight(data->horiz);
107 LONG lay_width = lm->lm_Layout.Width;
108 LONG lay_height = lm->lm_Layout.Height;
109 LONG cont_width = lay_width - _subwidth(data->contents);
110 LONG cont_height = lay_height - _subheight(data->contents);
111 BOOL vbar = FALSE, hbar = FALSE;
113 if (!data->usewinborder)
115 //kprintf("scrollgroup layout: %d x %d sub contents size %d,%d\n",
116 // lay_width, lay_height, _subwidth(data->contents), _subheight(data->contents));
118 /* layout the virtual group a first time, to determine the virtual width/height */
119 //MUI_Layout(data->contents,0,0,lay_width,lay_height,0);
121 get(data->contents, MUIA_Virtgroup_MinWidth, &virt_minwidth);
122 get(data->contents, MUIA_Virtgroup_MinHeight, &virt_minheight);
123 virt_minwidth -= _subwidth(data->contents);
124 virt_minheight -= _subheight(data->contents);
126 virt_maxwidth = _maxwidth(data->contents) - _subwidth(data->contents);
127 virt_maxheight = _maxheight(data->contents) - _subheight(data->contents);
129 virt_width = CLAMP(cont_width, virt_minwidth, virt_maxwidth);
130 virt_height = CLAMP(cont_height, virt_minheight, virt_maxheight);
132 if (virt_width > cont_width)
134 cont_height -= horiz_height;
135 virt_height = CLAMP(cont_height, virt_minheight, virt_maxheight);
136 hbar = TRUE;
138 //kprintf(" 1: %d x %d hbar %d vbar %d\n", cont_width, cont_height, hbar, vbar);
140 if (virt_height > cont_height)
142 cont_width -= vert_width;
143 virt_width = CLAMP(cont_width, virt_minwidth, virt_maxheight);
144 vbar = TRUE;
146 //kprintf(" 2: %d x %d hbar %d vbar %d\n", cont_width, cont_height, hbar, vbar);
148 /* We need to check this a 2nd time!! */
149 if (!hbar && (virt_width > cont_width))
151 cont_height -= horiz_height;
152 virt_height = CLAMP(cont_height, virt_minheight, virt_maxheight);
153 hbar = TRUE;
155 //kprintf(" 3: %d x %d hbar %d vbar %d\n", cont_width, cont_height, hbar, vbar);
157 } /* if (!data->usewinborder) */
159 cont_width += _subwidth(data->contents);
160 cont_height += _subheight(data->contents);
162 //kprintf("cont_size layouted to %d,%d\n", cont_width, cont_height);
164 if (hbar && vbar)
166 /* We need all scrollbars and the button */
167 set(data->vert, MUIA_ShowMe, TRUE); /* We could also overload MUIM_Show... */
168 set(data->horiz, MUIA_ShowMe, TRUE);
169 set(data->button, MUIA_ShowMe, TRUE);
170 MUI_Layout(data->vert, cont_width, 0, vert_width, cont_height,0);
171 MUI_Layout(data->horiz, 0, cont_height, cont_width, horiz_height, 0);
172 MUI_Layout(data->button, cont_width, cont_height, vert_width, horiz_height, 0);
174 else if (vbar)
176 set(data->vert, MUIA_ShowMe, TRUE);
177 set(data->horiz, MUIA_ShowMe, FALSE);
178 set(data->button, MUIA_ShowMe, FALSE);
180 MUI_Layout(data->vert, cont_width, 0, vert_width, cont_height,0);
182 else if (hbar)
184 set(data->vert, MUIA_ShowMe, FALSE);
185 set(data->horiz, MUIA_ShowMe, TRUE);
186 set(data->button, MUIA_ShowMe, FALSE);
188 MUI_Layout(data->horiz, 0, cont_height, cont_width, horiz_height, 0);
190 else if (!data->usewinborder)
192 set(data->vert, MUIA_ShowMe, FALSE);
193 set(data->horiz, MUIA_ShowMe, FALSE);
194 set(data->button, MUIA_ShowMe, FALSE);
197 /* Layout the group a second time, note that setting _mwidth() and _mheight() should be enough, or we invent a new flag */
198 MUI_Layout(data->contents,0,0,cont_width,cont_height,0);
200 //kprintf(" contents size after layout: %d x %d inner %d x %d\n",
201 // _width(data->contents), _height(data->contents),
202 // _mwidth(data->contents), _mheight(data->contents));
203 return 1;
206 return 0;
208 AROS_USERFUNC_EXIT
212 AROS_UFH3(ULONG,Scrollgroup_Function,
213 AROS_UFHA(struct Hook *, hook, A0),
214 AROS_UFHA(APTR, dummy, A2),
215 AROS_UFHA(void **, msg, A1))
217 AROS_USERFUNC_INIT
219 struct Scrollgroup_DATA *data = (struct Scrollgroup_DATA *)hook->h_Data;
220 int type = (int)msg[0];
221 LONG val = (LONG)msg[1];
223 switch (type)
225 case 1:
227 get(data->vert,MUIA_Prop_First,&val);
228 SetAttrs(data->contents,MUIA_Virtgroup_Top, val, MUIA_NoNotify, TRUE, MUIA_Group_Forward, FALSE, TAG_DONE);
229 break;
232 case 2:
234 get(data->horiz,MUIA_Prop_First,&val);
235 SetAttrs(data->contents,MUIA_Virtgroup_Left, val, MUIA_NoNotify, TRUE, MUIA_Group_Forward, FALSE, TAG_DONE);
236 break;
238 case 3: nnset(data->horiz, MUIA_Prop_First, val); break;
239 case 4: nnset(data->vert, MUIA_Prop_First, val); break;
241 return 0;
243 AROS_USERFUNC_EXIT
246 IPTR Scrollgroup__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
248 struct Scrollgroup_DATA *data;
249 //struct TagItem *tags,*tag;
250 Object *contents = (Object*)GetTagData(MUIA_Scrollgroup_Contents, 0, msg->ops_AttrList);
251 Object *vert,*horiz,*button,*group;
252 BOOL usewinborder;
253 Tag hbordertag = TAG_IGNORE;
254 Tag vbordertag = TAG_IGNORE;
256 struct Hook *layout_hook = mui_alloc_struct(struct Hook);
257 if (!layout_hook) return 0;
259 layout_hook->h_Entry = (HOOKFUNC)Scrollgroup_Layout_Function;
261 usewinborder = GetTagData(MUIA_Scrollgroup_UseWinBorder, FALSE, msg->ops_AttrList);
262 if (usewinborder)
264 hbordertag = MUIA_Prop_UseWinBorder;
265 vbordertag = MUIA_Prop_UseWinBorder;
268 obj = (Object *) DoSuperNewTags
270 cl, obj, NULL,
272 MUIA_Group_Horiz, FALSE,
273 Child, (IPTR) (group = (Object *)GroupObject,
274 MUIA_Group_LayoutHook, (IPTR) layout_hook,
275 Child, (IPTR) contents,
276 Child, (IPTR) (vert = (Object *)ScrollbarObject, MUIA_Group_Horiz, FALSE, vbordertag, MUIV_Prop_UseWinBorder_Right, End),
277 Child, (IPTR) (horiz = (Object *)ScrollbarObject, MUIA_Group_Horiz, TRUE, hbordertag, MUIV_Prop_UseWinBorder_Bottom, End),
278 Child, (IPTR) (button = (Object *)ScrollbuttonObject, End),
279 End),
281 TAG_DONE
284 if (!obj)
286 mui_free(layout_hook);
287 return 0;
290 data = INST_DATA(cl, obj);
291 data->vert = vert;
292 data->horiz = horiz;
293 data->button = button;
294 data->contents = contents;
295 data->usewinborder = usewinborder;
297 data->hook.h_Entry = (HOOKFUNC)Scrollgroup_Function;
298 data->hook.h_Data = data;
299 data->layout_hook = layout_hook;
300 layout_hook->h_Data = data;
302 DoMethod(vert, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 1, MUIV_TriggerValue);
303 DoMethod(horiz, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 2, MUIV_TriggerValue);
304 DoMethod(contents, MUIM_Group_DoMethodNoForward, MUIM_Notify, MUIA_Virtgroup_Left, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 3, MUIV_TriggerValue);
305 DoMethod(contents, MUIM_Group_DoMethodNoForward, MUIM_Notify, MUIA_Virtgroup_Top, MUIV_EveryTime, (IPTR)obj, 4, MUIM_CallHook, (IPTR)&data->hook, 4, MUIV_TriggerValue);
307 D(bug("Scrollgroup_New(%lx)\n", obj));
308 D(bug(" vert = %lx, horiz = %lx, button = %lx\n", vert, horiz, button));
309 return (IPTR)obj;
312 IPTR Scrollgroup__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
314 struct Scrollgroup_DATA *data = INST_DATA(cl, obj);
315 mui_free(data->layout_hook);
316 return DoSuperMethodA(cl,obj,msg);
319 IPTR Scrollgroup__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
321 struct Scrollgroup_DATA *data = INST_DATA(cl, obj);
322 LONG top,left,width,height;
324 get(data->contents, MUIA_Virtgroup_Left, &left);
325 get(data->contents, MUIA_Virtgroup_Top, &top);
326 get(data->contents, MUIA_Virtgroup_Width, &width);
327 get(data->contents, MUIA_Virtgroup_Height, &height);
329 SetAttrs(data->horiz, MUIA_Prop_First, left,
330 MUIA_Prop_Entries, width,
331 MUIA_Prop_Visible, _mwidth(data->contents),
332 TAG_DONE);
335 SetAttrs(data->vert, MUIA_Prop_First, top,
336 MUIA_Prop_Entries, height,
337 MUIA_Prop_Visible, _mheight(data->contents),
338 TAG_DONE);
340 return DoSuperMethodA(cl,obj,(Msg)msg);
343 #if ZUNE_BUILTIN_SCROLLGROUP
344 BOOPSI_DISPATCHER(IPTR, Scrollgroup_Dispatcher, cl, obj, msg)
346 switch (msg->MethodID)
348 case OM_NEW: return Scrollgroup__OM_NEW(cl, obj, (struct opSet *) msg);
349 case OM_DISPOSE: return Scrollgroup__OM_DISPOSE(cl, obj, msg);
350 case MUIM_Show: return Scrollgroup__MUIM_Show(cl, obj, (struct MUIP_Show*)msg);
351 default: return DoSuperMethodA(cl, obj, msg);
354 BOOPSI_DISPATCHER_END
356 const struct __MUIBuiltinClass _MUI_Scrollgroup_desc =
358 MUIC_Scrollgroup,
359 MUIC_Group,
360 sizeof(struct Scrollgroup_DATA),
361 (void*)Scrollgroup_Dispatcher
363 #endif /* ZUNE_BUILTIN_SCROLLGROUP */