make sure "S" is generated.
[AROS-Contrib.git] / bgui / progressclass.c
bloba5735bcf36280ecc47a1ddb3b9b5ce512f4c61cb
1 /*
2 * @(#) $Header$
4 * BGUI library
5 * progressclass.c
7 * (C) Copyright 1998 Manuel Lemos.
8 * (C) Copyright 1996-1997 Ian J. Einman.
9 * (C) Copyright 1993-1996 Jaba Development.
10 * (C) Copyright 1993-1996 Jan van den Baard.
11 * All Rights Reserved.
13 * $Log$
14 * Revision 42.2 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.1 2000/05/15 19:27:02 stegerg
18 * another hundreds of REG() macro replacements in func headers/protos.
20 * Revision 42.0 2000/05/09 22:09:53 mlemos
21 * Bumped to revision 42.0 before handing BGUI to AROS team
23 * Revision 41.11 2000/05/09 19:54:53 mlemos
24 * Merged with the branch Manuel_Lemos_fixes.
26 * Revision 41.10.2.3 1999/07/23 19:44:34 mlemos
27 * Added missing setting of text pen to draw the progress done value.
28 * Ensured that text drawing is done in complement mode if the text pen is the
29 * the same as the fill pen or background pen.
31 * Revision 41.10.2.2 1998/11/16 20:00:23 mlemos
32 * Replaced a FreeVec call by BGUI_FreePoolMem.
34 * Revision 41.10.2.1 1998/06/21 21:14:32 mlemos
35 * Prevented the Render method to draw an invalid size bar.
37 * Revision 41.10 1998/02/25 21:12:50 mlemos
38 * Bumping to 41.10
40 * Revision 1.1 1998/02/25 17:09:24 mlemos
41 * Ian sources
46 #include "include/classdefs.h"
48 /// Class definitions.
50 * The instance data used by the
51 * objects of this class.
53 typedef struct ProgressData {
54 LONG pd_Min; /* minimum progression */
55 LONG pd_Max; /* maximum progression */
56 LONG pd_Done; /* current progression */
57 LONG pd_Divisor; /* Done divisor */
58 UWORD pd_Flags; /* see below */
60 UBYTE *pd_Text;
61 UBYTE *pd_Buffer;
62 ULONG pd_BufSize;
63 struct TextFont *pd_Font;
64 } PD;
66 #define PDF_VERTICAL (1<<0)
68 ///
69 /// OM_NEW
71 * Create a shiny new object.
73 METHOD(ProgressClassNew, struct opSet *, ops)
75 PD *pd;
76 struct TagItem *tags;
77 IPTR rc;
79 tags = DefTagList(BGUI_PROGRESS_GADGET, ops->ops_AttrList);
82 * Let the superclass setup an object for us.
84 if ((rc = NewSuperObject(cl, obj, tags)))
86 pd = INST_DATA(cl, rc);
89 * Setup gadget.
91 pd->pd_Max = 100;
92 pd->pd_Divisor = 1;
94 AsmDoMethod((Object *)rc, OM_SET, ops->ops_AttrList, NULL);
96 FreeTagItems(tags);
98 return rc;
100 METHOD_END
102 /// OM_SET, OM_UPDATE
104 * Change the object attributes.
106 METHOD(ProgressClassSetUpdate, struct opUpdate *, opu)
108 PD *pd = INST_DATA(cl, obj);
109 ULONG tmp, odone = pd->pd_Done;
110 IPTR data;
111 struct TagItem *attr = opu->opu_AttrList, *tag;
112 struct TagItem *tstate = attr;
113 BOOL vc = FALSE;
116 * First let the superclass do it's thing.
118 AsmDoSuperMethodA(cl, obj, (Msg)opu);
121 * Set attributes we know.
123 while ((tag = NextTagItem(&tstate)))
125 data = tag->ti_Data;
126 switch ( tag->ti_Tag )
128 case PROGRESS_Min:
129 pd->pd_Min = data;
130 vc = TRUE;
131 break;
133 case PROGRESS_Max:
134 pd->pd_Max = data;
135 vc = TRUE;
136 break;
138 case PROGRESS_Done:
139 pd->pd_Done = data / pd->pd_Divisor;
140 vc = TRUE;
141 break;
143 case PROGRESS_Divisor:
144 pd->pd_Divisor = data ? data : 1;
145 break;
147 case PROGRESS_FormatString:
148 pd->pd_Text = (UBYTE *)data;
149 vc = TRUE;
150 break;
152 case PROGRESS_Vertical:
153 if (data) pd->pd_Flags |= PDF_VERTICAL;
154 else pd->pd_Flags &= ~PDF_VERTICAL;
155 vc = TRUE;
156 break;
158 case BT_TextAttr:
159 Get_SuperAttr(cl, obj, BT_TextFont, (IPTR *)&pd->pd_Font);
160 break;
165 * Sanity check.
167 if (pd->pd_Max < pd->pd_Min)
169 tmp = pd->pd_Min; pd->pd_Min = pd->pd_Max; pd->pd_Max = tmp;
171 else if (pd->pd_Max == pd->pd_Min)
172 pd->pd_Max++;
174 if (pd->pd_Done > pd->pd_Max) pd->pd_Done = pd->pd_Max;
175 else if (pd->pd_Done < pd->pd_Min) pd->pd_Done = pd->pd_Min;
178 * Do we need to change visually?
180 if (vc)
181 DoRenderMethod(obj, opu->opu_GInfo, GREDRAW_UPDATE);
184 * Notify the target.
186 if (odone != pd->pd_Done)
187 DoNotifyMethod(obj, opu->opu_GInfo, 0, GA_ID, GADGET(obj)->GadgetID, PROGRESS_Done, pd->pd_Done, TAG_END);
189 return 1;
191 METHOD_END
193 /// OM_DISPOSE
195 * Hmm, they want us out of here.
197 METHOD(ProgressClassDispose, Msg, msg)
199 PD *pd = INST_DATA(cl, obj);
202 * Deallocate the string buffer.
204 if (pd->pd_Buffer) BGUI_FreePoolMem(pd->pd_Buffer);
207 * And let the superclass take
208 * care of the rest.
210 return AsmDoSuperMethodA(cl, obj, msg);
212 METHOD_END
214 /// BASE_RENDER
216 * Scale the area of the indicator
217 * that needs to be filled.
219 #define ScaleFill(s,m,d) UDivMod32( UMult32( d, s ) + UDivMod32( m, 2 ), m )
222 * Render the gadget imagery
224 METHOD(ProgressClassRender, struct bmRender *, bmr)
226 PD *pd = INST_DATA(cl, obj);
227 BC *bc = BASE_DATA(obj);
228 struct BaseInfo *bi = bmr->bmr_BInfo;
229 struct RastPort *rp = bi->bi_RPort;
230 struct IBox box1, box2;
231 LONG done, min, max;
232 LONG filled, space;
233 UBYTE *str;
236 * Render the baseclass.
238 AsmDoSuperMethodA(cl, obj, (Msg)bmr);
240 min = pd->pd_Min;
241 max = pd->pd_Max;
242 done = pd->pd_Done;
244 box1 = bc->bc_InnerBox;
245 box2 = bc->bc_InnerBox;
247 space = (pd->pd_Flags & PDF_VERTICAL) ? box1.Height : box1.Width;
250 * Scale fill.
252 filled = ScaleFill(space, ABS(max - min), ABS(done));
255 * Keep within the bounds.
257 if (done >= max) filled = space;
258 else if (done <= min) filled = 0;
259 if (filled > space) filled = space;
262 * Vertical indication?
264 if (!(pd->pd_Flags & PDF_VERTICAL))
266 box1.Width = filled;
267 box2.Left += filled;
268 box2.Width -= filled;
270 else
272 box1.Top += box1.Height - filled;
273 box1.Height = filled;
274 box2.Height -= filled;
278 * Convert to Rectangle structures.
279 * Render filled area and clear the rest.
281 if(box1.Width>0
282 && box1.Height>0)
284 box1.Width += box1.Left - 1;
285 box1.Height += box1.Top - 1;
286 AsmDoMethod(bc->bc_Frame, FRAMEM_BACKFILL, bi, &box1, IDS_SELECTED);
288 if(box2.Width>0
289 && box2.Height>0)
291 box2.Width += box2.Left - 1;
292 box2.Height += box2.Top - 1;
293 AsmDoMethod(bc->bc_Frame, FRAMEM_BACKFILL, bi, &box2, IDS_NORMAL);
297 * Render textual indicator when present.
299 if (pd->pd_Text)
302 * Setup the font.
304 if (pd->pd_Font) BSetFont(bi, pd->pd_Font);
307 * Do we have a text?
309 if ((str = DoBuffer(pd->pd_Text, &pd->pd_Buffer, &pd->pd_BufSize, (RAWARG)&pd->pd_Done)) && strlen(str))
311 ULONG apen;
312 STRPTR formatted=NULL;
314 BGUI_InfoTextSize(rp, str, (UWORD *)&box1.Width, (UWORD *)&box1.Height);
316 box1.Left = bc->bc_InnerBox.Left + ((bc->bc_InnerBox.Width - box1.Width) >> 1);
317 box1.Top = bc->bc_InnerBox.Top + ((bc->bc_InnerBox.Height - box1.Height) >> 1);
319 FSetAPen(rp,apen=bi->bi_DrInfo->dri_Pens[TEXTPEN]);
320 if((apen!=bi->bi_DrInfo->dri_Pens[FILLPEN]
321 && apen!=bi->bi_DrInfo->dri_Pens[BACKGROUNDPEN])
322 || (formatted=BGUI_AllocPoolMem(strlen(ISEQ_COMPLEMENT)+strlen(str)+1)))
324 if(formatted)
326 strcpy(formatted,ISEQ_COMPLEMENT);
327 strcpy(formatted+strlen(ISEQ_COMPLEMENT),str);
328 str=formatted;
330 RenderText(bi, str, &box1);
331 if(formatted)
332 BGUI_FreePoolMem(formatted);
336 return 1;
338 METHOD_END
340 /// OM_GET
342 * They want to know an attribute value.
344 METHOD(ProgressClassGet, struct opGet *, opg)
346 PD *pd = INST_DATA(cl, obj);
347 ULONG rc = 1;
348 IPTR *store = opg->opg_Storage;
350 switch (opg->opg_AttrID)
352 case PROGRESS_Done:
353 STORE pd->pd_Done;
354 break;
356 default:
357 rc = AsmDoSuperMethodA(cl, obj, (Msg)opg);
358 break;
360 return rc;
362 METHOD_END
364 /// GM_HITTEST
366 * We do not respond to
367 * clicking in the gadget.
369 METHOD(ProgressClassHitTest, struct gpHitTest *, gph)
371 return 0;
373 METHOD_END
375 /// BASE_DIMENSIONS
377 * Our parent group needs to know
378 * something about our dimensions.
380 METHOD(ProgressClassDimensions, struct bmDimensions *, bmd)
382 PD *pd = INST_DATA(cl, obj);
383 struct RastPort *rp = bmd->bmd_BInfo->bi_RPort;
384 UWORD mw = 2, mh = 2, l;
385 UBYTE *str;
388 * Any text?
390 if (pd->pd_Text)
393 * Obtain string.
395 if ((str = DoBuffer(pd->pd_Text, &pd->pd_Buffer, &pd->pd_BufSize, (RAWARG)&pd->pd_Min)))
398 * Compute size of minimum level.
400 l = TotalWidth(rp, str);
403 * Obtain string.
405 if ((str = DoBuffer(pd->pd_Text, &pd->pd_Buffer, &pd->pd_BufSize, (RAWARG)&pd->pd_Max)))
408 * Compute size of maximum level.
410 mw = TotalWidth (rp, str);
411 mh = TotalHeight(rp, str);
414 * Take the largest.
416 mw = (mw > l) ? mw : l;
419 * Add the width of 2/3 of a single space.
421 mw += (TextWidthNum(rp, " ", 1) / 3);
426 * Setup minimum dimensions.
428 return CalcDimensions(cl, obj, bmd, mw, mh);
430 METHOD_END
432 /// Class initialization.
434 * Function table.
436 STATIC DPFUNC ClassFunc[] = {
437 { BASE_RENDER, ProgressClassRender, },
438 { BASE_DIMENSIONS, ProgressClassDimensions, },
440 { OM_NEW, ProgressClassNew, },
441 { OM_GET, ProgressClassGet, },
442 { OM_SET, ProgressClassSetUpdate, },
443 { OM_UPDATE, ProgressClassSetUpdate, },
444 { OM_DISPOSE, ProgressClassDispose, },
445 { GM_HITTEST, ProgressClassHitTest, },
446 { DF_END, NULL },
450 * Initialize the progress class.
452 makeproto Class *InitProgressClass(void)
454 return BGUI_MakeClass(CLASS_SuperClassBGUI, BGUI_BASE_GADGET,
455 CLASS_ObjectSize, sizeof(PD),
456 CLASS_DFTable, ClassFunc,
457 TAG_DONE);