linux/bootstrap: use Forbid/Permit only when thread is main AROS thread
[AROS.git] / workbench / system / Workbook / wbvirtual.c
blobaee42b26bc17c360c5b6620f00c5e7eca927f15f
1 /*
2 Copyright © 2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Workbook Virtual Area Class
6 Lang: english
7 */
9 #define DEBUG 0
10 #include <aros/debug.h>
12 #include <string.h>
13 #include <limits.h>
15 #include <proto/dos.h>
16 #include <proto/exec.h>
17 #include <proto/intuition.h>
18 #include <proto/utility.h>
19 #include <proto/gadtools.h>
20 #include <proto/workbench.h>
21 #include <proto/graphics.h>
22 #include <proto/layers.h>
24 #include <intuition/classusr.h>
25 #include <intuition/icclass.h>
26 #include <intuition/cghooks.h>
27 #include <libraries/gadtools.h>
29 #include "workbook_intern.h"
30 #include "classes.h"
32 static inline WORD max(WORD a, WORD b)
34 return (a > b) ? a : b;
37 struct wbVirtual {
38 Object *Gadget;
39 struct IBox Virt; /* Virtual pos in, and total size of the scroll area */
42 static BOOL wbRedimension(Class *cl, Object *obj, WORD vwidth, WORD vheight)
44 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
45 struct wbVirtual *my = INST_DATA(cl, obj);
46 struct Gadget *gadget = (struct Gadget *)obj;
47 BOOL rc = FALSE;
49 if ((my->Virt.Width != vwidth) ||
50 (my->Virt.Height != vheight))
51 rc = TRUE;
53 my->Virt.Width = vwidth;
54 my->Virt.Height = vheight;
56 if (my->Virt.Left > (my->Virt.Width - gadget->Width)) {
57 my->Virt.Left = max(0, my->Virt.Width - gadget->Width);
58 rc = TRUE;
61 if (my->Virt.Top > (my->Virt.Height - gadget->Height)) {
62 my->Virt.Top = max(0, my->Virt.Height - gadget->Height);
63 rc = TRUE;
66 D(bug("WBVirtual: wbRedimension(%d,%d) = (%d,%d) %dx%d\n",
67 vwidth,vheight,my->Virt.Left,my->Virt.Top,
68 my->Virt.Width, my->Virt.Height));
69 D(bug("WBVirtual: Frame at: (%d,%d) %dx%d\n",
70 gadget->TopEdge, gadget->LeftEdge,
71 gadget->Width, gadget->Height));
73 if (my->Gadget) {
74 SetAttrs(my->Gadget, GA_Top, gadget->TopEdge - my->Virt.Top,
75 GA_Left, gadget->LeftEdge - my->Virt.Left,
76 TAG_END);
79 return rc;
82 static BOOL wbMoveTo(Class *cl, Object *obj, WORD left, WORD top)
84 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
85 struct wbVirtual *my = INST_DATA(cl, obj);
86 struct Gadget *gadget = (struct Gadget *)obj;
87 WORD dLeft, dTop;
89 D(bug("GadgetSize %dx%d\n", gadget->Width, gadget->Width));
90 D(bug(" VirtSize %dx%d\n", my->Virt.Width, my->Virt.Height));
91 D(bug(" wbMoveTo(%d,%d) =", left,top));
93 if (left > (my->Virt.Width - gadget->Width))
94 left = max(0, my->Virt.Width - gadget->Width);
95 if (top > (my->Virt.Height - gadget->Height))
96 top = max(0, my->Virt.Height - gadget->Height);
98 dLeft = left - my->Virt.Left;
99 dTop = top - my->Virt.Top;
101 D(bug(" (%d,%d) %dx%d\n",
102 left, top,
103 my->Virt.Width, my->Virt.Height));
105 if (dLeft == 0 && dTop == 0)
106 return FALSE;
108 my->Virt.Left = left;
109 my->Virt.Top = top;
111 D(bug("Frame at: (%d,%d) %dx%d\n",
112 gadget->TopEdge, gadget->LeftEdge,
113 gadget->Width, gadget->Height));
115 /* Set the position of the child */
116 if (my->Gadget) {
117 SetAttrs(my->Gadget, GA_Top, gadget->TopEdge - my->Virt.Top,
118 GA_Left, gadget->LeftEdge - my->Virt.Left);
121 return TRUE;
125 static IPTR WBVirtualNew(Class *cl, Object *obj, struct opSet *ops)
127 IPTR rc = 0;
129 rc = DoSuperMethodA(cl, obj, (Msg)ops);
130 if (rc == 0)
131 return rc;
133 obj = (Object *)rc;
135 DoMethod(obj, OM_SET, ops->ops_AttrList, ops->ops_GInfo);
137 return rc;
140 // OM_GET
141 static IPTR WBVirtualGet(Class *cl, Object *obj, struct opGet *opg)
143 struct wbVirtual *my = INST_DATA(cl, obj);
144 IPTR rc = TRUE;
146 switch (opg->opg_AttrID) {
147 case WBVA_Gadget:
148 *(opg->opg_Storage) = (IPTR)(my->Gadget);
149 break;
150 case WBVA_VirtLeft:
151 *(opg->opg_Storage) = (IPTR)(SIPTR)(my->Virt.Left);
152 break;
153 case WBVA_VirtTop:
154 *(opg->opg_Storage) = (IPTR)(SIPTR)(my->Virt.Top);
155 break;
156 case WBVA_VirtWidth:
157 *(opg->opg_Storage) = (IPTR)(SIPTR)(my->Virt.Width);
158 break;
159 case WBVA_VirtHeight:
160 *(opg->opg_Storage) = (IPTR)(SIPTR)(my->Virt.Height);
161 break;
162 default:
163 rc = DoSuperMethodA(cl, obj, (Msg)opg);
164 break;
167 return rc;
170 // OM_UPDATE/OM_SET
171 static IPTR WBVirtualSetUpdate(Class *cl, Object *obj, struct opUpdate *opu)
173 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
174 struct wbVirtual *my = INST_DATA(cl, obj);
175 struct TagItem *tag;
176 struct TagItem *tstate;
177 IPTR rc;
178 WORD val;
180 rc = DoSuperMethodA(cl, obj, (Msg)opu);
182 if ((opu->MethodID == OM_UPDATE) && (opu->opu_Flags & OPUF_INTERIM))
183 return rc;
185 tstate = opu->opu_AttrList;
186 while ((tag = NextTagItem(&tstate))) {
187 val = (WORD)tag->ti_Data;
188 D(bug("%s: Tag=0x%x, val=%d\n", __func__, tag->ti_Tag, val));
189 switch (tag->ti_Tag) {
190 case WBVA_Gadget:
191 if (my->Gadget != (Object *)tag->ti_Data) {
192 my->Gadget = (Object *)tag->ti_Data;
193 IPTR vwidth = 0, vheight = 0;
194 GetAttr(GA_Width, my->Gadget, &vwidth);
195 GetAttr(GA_Height, my->Gadget, &vheight);
196 rc |= wbRedimension(cl, obj, vwidth, vheight);
198 break;
199 case WBVA_VirtTop:
200 rc |= wbMoveTo(cl, obj, my->Virt.Left, val);
201 break;
202 case WBVA_VirtLeft:
203 rc |= wbMoveTo(cl, obj, val, my->Virt.Top);
204 break;
205 case WBVA_VirtHeight:
206 rc |= wbRedimension(cl, obj, my->Virt.Width, val);
207 break;
208 case WBVA_VirtWidth:
209 rc |= wbRedimension(cl, obj, val, my->Virt.Height);
210 break;
211 case GA_Width:
212 case GA_Height:
213 rc |= wbRedimension(cl, obj, my->Virt.Width, my->Virt.Height);
214 break;
215 default:
216 break;
220 return rc;
223 // GM_HITTEST
224 static IPTR WBVirtualHitTest(Class *cl, Object *obj, struct gpHitTest *gph)
226 struct wbVirtual *my = INST_DATA(cl, obj);
227 struct gpHitTest subtest = *gph;
229 if (!my->Gadget)
230 return 0;
232 /* Forward to our client */
233 subtest.gpht_Mouse.X += my->Virt.Left;
234 subtest.gpht_Mouse.Y += my->Virt.Top;
236 return DoMethodA(my->Gadget, (Msg)&subtest);
239 // GM_RENDER
240 static IPTR WBVirtualRender(Class *cl, Object *obj, struct gpRender *gpr)
242 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
243 struct wbVirtual *my = INST_DATA(cl, obj);
244 struct Gadget *gadget = (struct Gadget *)obj;
245 struct GadgetInfo *ginfo = gpr->gpr_GInfo;
247 if (my->Gadget == NULL)
248 return FALSE;
250 if (ginfo == NULL)
251 return FALSE;
253 /* Redraw the child */
254 struct Region *region, *old;
255 if ((region = NewRegion())) {
256 struct Rectangle rect = {
257 .MinX = gadget->LeftEdge,
258 .MinY = gadget->TopEdge,
259 .MaxX = gadget->LeftEdge + gadget->Width - 1,
260 .MaxY = gadget->TopEdge + gadget->Height - 1,
262 OrRectRegion(region, &rect);
263 old = InstallClipRegion(ginfo->gi_Layer, region);
264 AddGadget(ginfo->gi_Window, (struct Gadget *)my->Gadget, 0);
265 RefreshGList((struct Gadget *)my->Gadget, ginfo->gi_Window, ginfo->gi_Requester, 1);
266 RemoveGadget(ginfo->gi_Window, (struct Gadget *)my->Gadget);
267 InstallClipRegion(ginfo->gi_Layer, old);
268 DisposeRegion(region);
271 return TRUE;
274 // GM_GOACTIVE
275 static IPTR WBVirtualGoActive(Class *cl, Object *obj, struct gpInput *gpi)
277 struct wbVirtual *my = INST_DATA(cl, obj);
278 struct gpInput m;
280 m = *gpi;
281 m.gpi_Mouse.X += my->Virt.Left;
282 m.gpi_Mouse.Y += my->Virt.Top;
284 return DoMethodA(my->Gadget, (Msg)&m);
287 // GM_GOINACTIVE
288 static IPTR WBVirtualGoInactive(Class *cl, Object *obj, struct gpGoInactive *gpgi)
290 struct wbVirtual *my = INST_DATA(cl, obj);
292 return DoMethodA(my->Gadget, (Msg)gpgi);
295 // GM_HANDLEINPUT
296 static IPTR WBVirtualHandleInput(Class *cl, Object *obj, struct gpInput *gpi)
298 struct wbVirtual *my = INST_DATA(cl, obj);
299 struct gpInput m;
301 m = *gpi;
302 m.gpi_Mouse.X += my->Virt.Left;
303 m.gpi_Mouse.Y += my->Virt.Top;
305 return DoMethodA(my->Gadget, (Msg)&m);
308 static IPTR dispatcher(Class *cl, Object *obj, Msg msg)
310 IPTR rc = 0;
312 switch (msg->MethodID) {
313 case OM_NEW: rc = WBVirtualNew(cl, obj, (APTR)msg); break;
314 case OM_GET: rc = WBVirtualGet(cl, obj, (APTR)msg); break;
315 case OM_SET:
316 case OM_UPDATE: rc = WBVirtualSetUpdate(cl, obj, (APTR)msg); break;
317 case GM_RENDER: rc = WBVirtualRender(cl, obj, (APTR)msg); break;
318 case GM_HITTEST: rc = WBVirtualHitTest(cl, obj, (APTR)msg); break;
319 case GM_GOACTIVE: rc = WBVirtualGoActive(cl, obj, (APTR)msg); break;
320 case GM_GOINACTIVE: rc = WBVirtualGoInactive(cl, obj, (APTR)msg); break;
321 case GM_HANDLEINPUT: rc = WBVirtualHandleInput(cl, obj, (APTR)msg); break;
322 default: rc = DoSuperMethodA(cl, obj, msg); break;
325 return rc;
328 Class *WBVirtual_MakeClass(struct WorkbookBase *wb)
330 Class *cl;
332 cl = MakeClass( NULL, "gadgetclass", NULL,
333 sizeof(struct wbVirtual),
335 if (cl != NULL) {
336 cl->cl_Dispatcher.h_Entry = HookEntry;
337 cl->cl_Dispatcher.h_SubEntry = dispatcher;
338 cl->cl_Dispatcher.h_Data = NULL;
339 cl->cl_UserData = (IPTR)wb;
342 return cl;