Icons for Radium and Shellplayer.
[AROS-Contrib.git] / bgui / progressclass.c
blob24e445685ba846d3dfec9f0a02734ceae6093480
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;
234 IPTR tmp;
237 * Render the baseclass.
239 AsmDoSuperMethodA(cl, obj, (Msg)bmr);
241 min = pd->pd_Min;
242 max = pd->pd_Max;
243 done = pd->pd_Done;
245 box1 = bc->bc_InnerBox;
246 box2 = bc->bc_InnerBox;
248 space = (pd->pd_Flags & PDF_VERTICAL) ? box1.Height : box1.Width;
251 * Scale fill.
253 filled = ScaleFill(space, ABS(max - min), ABS(done));
256 * Keep within the bounds.
258 if (done >= max) filled = space;
259 else if (done <= min) filled = 0;
260 if (filled > space) filled = space;
263 * Vertical indication?
265 if (!(pd->pd_Flags & PDF_VERTICAL))
267 box1.Width = filled;
268 box2.Left += filled;
269 box2.Width -= filled;
271 else
273 box1.Top += box1.Height - filled;
274 box1.Height = filled;
275 box2.Height -= filled;
279 * Convert to Rectangle structures.
280 * Render filled area and clear the rest.
282 if(box1.Width>0
283 && box1.Height>0)
285 box1.Width += box1.Left - 1;
286 box1.Height += box1.Top - 1;
287 AsmDoMethod(bc->bc_Frame, FRAMEM_BACKFILL, bi, &box1, IDS_SELECTED);
289 if(box2.Width>0
290 && box2.Height>0)
292 box2.Width += box2.Left - 1;
293 box2.Height += box2.Top - 1;
294 AsmDoMethod(bc->bc_Frame, FRAMEM_BACKFILL, bi, &box2, IDS_NORMAL);
298 * Render textual indicator when present.
300 if (pd->pd_Text)
303 * Setup the font.
305 if (pd->pd_Font) BSetFont(bi, pd->pd_Font);
308 * Do we have a text?
310 tmp = pd->pd_Done;
311 if ((str = DoBuffer(pd->pd_Text, &pd->pd_Buffer, &pd->pd_BufSize, &tmp)) && strlen(str))
313 ULONG apen;
314 STRPTR formatted=NULL;
316 BGUI_InfoTextSize(rp, str, (UWORD *)&box1.Width, (UWORD *)&box1.Height);
318 box1.Left = bc->bc_InnerBox.Left + ((bc->bc_InnerBox.Width - box1.Width) >> 1);
319 box1.Top = bc->bc_InnerBox.Top + ((bc->bc_InnerBox.Height - box1.Height) >> 1);
321 FSetAPen(rp,apen=bi->bi_DrInfo->dri_Pens[TEXTPEN]);
322 if((apen!=bi->bi_DrInfo->dri_Pens[FILLPEN]
323 && apen!=bi->bi_DrInfo->dri_Pens[BACKGROUNDPEN])
324 || (formatted=BGUI_AllocPoolMem(strlen(ISEQ_COMPLEMENT)+strlen(str)+1)))
326 if(formatted)
328 strcpy(formatted,ISEQ_COMPLEMENT);
329 strcpy(formatted+strlen(ISEQ_COMPLEMENT),str);
330 str=formatted;
332 RenderText(bi, str, &box1);
333 if(formatted)
334 BGUI_FreePoolMem(formatted);
338 return 1;
340 METHOD_END
342 /// OM_GET
344 * They want to know an attribute value.
346 METHOD(ProgressClassGet, struct opGet *, opg)
348 PD *pd = INST_DATA(cl, obj);
349 ULONG rc = 1;
350 IPTR *store = opg->opg_Storage;
352 switch (opg->opg_AttrID)
354 case PROGRESS_Done:
355 STORE pd->pd_Done;
356 break;
358 default:
359 rc = AsmDoSuperMethodA(cl, obj, (Msg)opg);
360 break;
362 return rc;
364 METHOD_END
366 /// GM_HITTEST
368 * We do not respond to
369 * clicking in the gadget.
371 METHOD(ProgressClassHitTest, struct gpHitTest *, gph)
373 return 0;
375 METHOD_END
377 /// BASE_DIMENSIONS
379 * Our parent group needs to know
380 * something about our dimensions.
382 METHOD(ProgressClassDimensions, struct bmDimensions *, bmd)
384 PD *pd = INST_DATA(cl, obj);
385 struct RastPort *rp = bmd->bmd_BInfo->bi_RPort;
386 UWORD mw = 2, mh = 2, l;
387 UBYTE *str;
390 * Any text?
392 if (pd->pd_Text)
395 * Obtain string.
397 if ((str = DoBuffer(pd->pd_Text, &pd->pd_Buffer, &pd->pd_BufSize, (IPTR *)&pd->pd_Min)))
400 * Compute size of minimum level.
402 l = TotalWidth(rp, str);
405 * Obtain string.
407 if ((str = DoBuffer(pd->pd_Text, &pd->pd_Buffer, &pd->pd_BufSize, (IPTR *)&pd->pd_Max)))
410 * Compute size of maximum level.
412 mw = TotalWidth (rp, str);
413 mh = TotalHeight(rp, str);
416 * Take the largest.
418 mw = (mw > l) ? mw : l;
421 * Add the width of 2/3 of a single space.
423 mw += (TextWidthNum(rp, " ", 1) / 3);
428 * Setup minimum dimensions.
430 return CalcDimensions(cl, obj, bmd, mw, mh);
432 METHOD_END
434 /// Class initialization.
436 * Function table.
438 STATIC DPFUNC ClassFunc[] = {
439 { BASE_RENDER, ProgressClassRender, },
440 { BASE_DIMENSIONS, ProgressClassDimensions, },
442 { OM_NEW, ProgressClassNew, },
443 { OM_GET, ProgressClassGet, },
444 { OM_SET, ProgressClassSetUpdate, },
445 { OM_UPDATE, ProgressClassSetUpdate, },
446 { OM_DISPOSE, ProgressClassDispose, },
447 { GM_HITTEST, ProgressClassHitTest, },
448 { DF_END, NULL },
452 * Initialize the progress class.
454 makeproto Class *InitProgressClass(void)
456 return BGUI_MakeClass(CLASS_SuperClassBGUI, BGUI_BASE_GADGET,
457 CLASS_ObjectSize, sizeof(PD),
458 CLASS_DFTable, ClassFunc,
459 TAG_DONE);