Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / libs / asl / listviewclass.c
bloba2db6c6c7fddc335d15223c744ece7d4f50c80ce
1 /*
2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <proto/exec.h>
7 #include <proto/dos.h>
8 #include <proto/utility.h>
9 #include <proto/intuition.h>
10 #include <proto/graphics.h>
11 #include <proto/cybergraphics.h>
12 #include <proto/layers.h>
13 #include <exec/memory.h>
14 #include <intuition/screens.h>
15 #include <intuition/icclass.h>
16 #include <intuition/cghooks.h>
17 #include <intuition/imageclass.h>
18 #include <intuition/gadgetclass.h>
19 #include <graphics/gfx.h>
20 #include <cybergraphx/cybergraphics.h>
22 #include <string.h>
24 #include "asl_intern.h"
25 #include "layout.h"
27 #define SDEBUG 0
28 #define DEBUG 0
30 #include <aros/debug.h>
32 #define CLASS_ASLBASE ((struct AslBase_intern *)cl->cl_UserData)
33 #define HOOK_ASLBASE ((struct AslBase_intern *)hook->h_Data)
35 #define AslBase CLASS_ASLBASE
37 /***********************************************************************************/
39 #undef AslBase
40 #define AslBase HOOK_ASLBASE
42 /************************
43 ** ASLLVRenderHook() **
44 ************************/
45 AROS_UFH3(IPTR, ASLLVRenderHook,
46 AROS_UFHA(struct Hook *, hook, A0),
47 AROS_UFHA(struct Node *, node, A2),
48 AROS_UFHA(struct ASLLVDrawMsg *, msg, A1)
51 AROS_USERFUNC_INIT
53 IPTR retval;
55 if (msg->lvdm_MethodID == LV_DRAW)
57 struct DrawInfo *dri = msg->lvdm_DrawInfo;
58 struct RastPort *rp = msg->lvdm_RastPort;
60 WORD min_x = msg->lvdm_Bounds.MinX;
61 WORD min_y = msg->lvdm_Bounds.MinY;
62 WORD max_x = msg->lvdm_Bounds.MaxX;
63 WORD max_y = msg->lvdm_Bounds.MaxY;
65 UWORD erasepen = BACKGROUNDPEN;
66 UWORD textpen = TEXTPEN;
68 SetDrMd(rp, JAM1);
71 switch (msg->lvdm_State)
73 case ASLLVR_SELECTED:
74 erasepen = FILLPEN;
75 textpen = FILLTEXTPEN;
77 /* Fall through */
79 case ASLLVR_NORMAL:
81 WORD numfit;
82 struct TextExtent te;
84 SetAPen(rp, dri->dri_Pens[erasepen]);
85 RectFill(rp, min_x, min_y, max_x, max_y);
87 if (node) if (node->ln_Name)
89 UWORD len = strlen(node->ln_Name);
91 numfit = TextFit(rp,
92 node->ln_Name,
93 len,
94 &te,
95 NULL,
97 max_x - min_x + 1 - BORDERLVITEMSPACINGX * 2,
98 max_y - min_y + 1);
100 if (numfit < len) numfit++;
102 SetAPen(rp, dri->dri_Pens[textpen]);
104 /* Render text */
105 Move(rp, min_x + BORDERLVITEMSPACINGX,
106 min_y + BORDERLVITEMSPACINGY + rp->Font->tf_Baseline);
107 Text(rp, node->ln_Name, numfit);
110 } break;
113 retval = ASLLVCB_OK;
115 else
117 retval = ASLLVCB_UNKNOWN;
120 return retval;
122 AROS_USERFUNC_EXIT
125 /***********************************************************************************/
127 #undef AslBase
128 #define AslBase CLASS_ASLBASE
130 static struct Node *findnode(Class *cl, Object *o, WORD which)
132 struct AslListViewData *data;
133 struct Node *node = NULL;
135 data = INST_DATA(cl, o);
137 if (data->nodetable)
139 if ((which < data->total) && (which >= 0)) node = data->nodetable[which];
140 } else {
141 node = FindListNode(data->labels, which);
144 return node;
147 /***********************************************************************************/
149 static void makenodetable(Class *cl, Object *o)
151 struct AslListViewData *data;
153 data = INST_DATA(cl, o);
155 if (data->nodetable)
157 FreeVec(data->nodetable);
158 data->nodetable = NULL;
161 /* data->total must be correct here */
163 if (data->total > 0)
165 if ((data->nodetable = AllocVec(sizeof(struct Node *) * data->total, MEMF_PUBLIC)))
167 struct Node *node, **nodeptr = data->nodetable;
168 ForeachNode(data->labels, node)
170 *nodeptr++ = node;
176 /***********************************************************************************/
178 static void renderitem(Class *cl, Object *o, struct Node *node, WORD liney, struct RastPort *rp)
180 struct AslListViewData *data;
181 struct ASLLVDrawMsg msg;
183 data = INST_DATA(cl, o);
185 if (data->font) SetFont(rp, data->font);
187 msg.lvdm_MethodID = ASLLV_DRAW;
188 msg.lvdm_RastPort = rp;
189 msg.lvdm_DrawInfo = data->ld->ld_Dri;
190 msg.lvdm_Bounds.MinX = data->minx + BORDERLVSPACINGX;
191 msg.lvdm_Bounds.MaxX = data->maxx - BORDERLVSPACINGX;
192 msg.lvdm_Bounds.MinY = data->miny + BORDERLVSPACINGY + liney * data->lineheight -
193 (data->toppixel % data->lineheight);
194 msg.lvdm_Bounds.MaxY = msg.lvdm_Bounds.MinY + data->lineheight - 1;
195 msg.lvdm_State = node ? (IS_SELECTED(node) ? ASLLVR_SELECTED : ASLLVR_NORMAL) : ASLLVR_NORMAL;
197 if (data->renderrect)
199 if (!AndRectRect(data->renderrect, &msg.lvdm_Bounds, NULL)) return;
202 CallHookPkt(data->renderhook, node, &msg);
205 /***********************************************************************************/
207 static void renderallitems(Class *cl, Object *o, struct RastPort *rp)
209 struct AslListViewData *data;
210 struct Node *node;
211 LONG i, visible;
213 data = INST_DATA(cl, o);
215 node = findnode(cl, o, data->top);
217 visible = data->visiblepixels + data->lineheight - 1 + (data->toppixel % data->lineheight);
218 visible /= data->lineheight;
220 //kprintf("renderallitem: lineheight %d visible %d visiblepixels %d toppixel %d\n",
221 // data->lineheight, visible, data->visiblepixels, data->toppixel);
223 for(i = 0; i < visible; i++)
225 if (node) if (!node->ln_Succ) node = NULL;
227 renderitem(cl, o, node , i, rp);
229 if (node) node = node->ln_Succ;
233 /***********************************************************************************/
235 static void rendersingleitem(Class *cl, Object *o, struct GadgetInfo *gi, WORD which)
237 struct AslListViewData *data;
239 data = INST_DATA(cl, o);
241 if (!gi) return;
242 if (which < data->top) return;
243 if (which >= data->total) return;
245 if ((which - data->top) <
246 (data->visiblepixels + data->lineheight - 1 + (data->toppixel % data->lineheight)) / data->lineheight)
248 struct RastPort *rp;
249 struct Node *node;
251 node = findnode(cl, o, which);
253 if ((rp = ObtainGIRPort(gi)))
255 struct gpRender gpr;
257 data->rendersingleitem = which;
259 gpr.MethodID = GM_RENDER;
260 gpr.gpr_GInfo = gi;
261 gpr.gpr_RPort = rp;
262 gpr.gpr_Redraw = GREDRAW_UPDATE;
264 DoMethodA(o, (Msg)&gpr);
266 ReleaseGIRPort(rp);
268 } /* if ((rp = ObtainGIRPort(msg->gpi_GInfo))) */
270 } /* if ((which >= data->top) && ... */
274 /***********************************************************************************/
276 static WORD mouseitem(Class *cl, Object *o, WORD mousex, WORD mousey)
278 struct AslListViewData *data;
279 WORD result = -5;
281 data = INST_DATA(cl, o);
283 if (mousey < BORDERLVSPACINGY)
285 result = -1;
287 else if (mousey > data->maxy - data->miny - BORDERLVSPACINGY)
289 result = -2;
291 else if (mousex < BORDERLVSPACINGX)
293 result = -3;
295 else if (mousex > data->maxx - data->minx - BORDERLVSPACINGX)
297 result = -4;
299 else
301 LONG i = (mousey - BORDERLVSPACINGY + (data->toppixel % data->lineheight)) / data->lineheight;
302 LONG visible;
304 visible = data->visiblepixels + data->lineheight - 1 + (data->toppixel % data->lineheight);
305 visible /= data->lineheight;
307 if (i < visible)
309 struct Node *node;
311 i += data->top;
313 if ((node = findnode(cl, o, i)))
315 result = i;
320 //kprintf("mouseitem : %d\n", result);
322 return result;
325 /***********************************************************************************/
327 static void notifyall(Class *cl, Object *o, struct GadgetInfo *gi, STACKULONG flags)
329 struct AslListViewData *data = INST_DATA(cl, o);
330 struct TagItem tags[] =
332 {ASLLV_Top , data->top },
333 {ASLLV_TopPixel , data->toppixel },
334 {ASLLV_Total , data->total },
335 {ASLLV_TotalPixels , data->totalpixels },
336 {ASLLV_Visible , data->visible },
337 {ASLLV_VisiblePixels, data->visiblepixels },
338 {ASLLV_DeltaFactor , data->lineheight },
339 {TAG_DONE }
341 struct opUpdate opu;
343 opu.MethodID = OM_NOTIFY;
344 opu.opu_AttrList = tags;
345 opu.opu_GInfo = gi;
346 opu.opu_Flags = flags;
348 D(bug("asl listview notify all: top = %d (%d) total = %d (%d) visible = %d (%d)\n",
349 data->top, data->toppixel,
350 data->total, data->totalpixels,
351 data->visible, data->visiblepixels));
353 DoSuperMethodA(cl, o, (Msg)&opu);
357 /***********************************************************************************/
359 static void notifytop(Class *cl, Object *o, struct GadgetInfo *gi, STACKULONG flags)
361 struct AslListViewData *data = INST_DATA(cl, o);
362 struct TagItem tags[] =
364 {ASLLV_Top , data->top },
365 {ASLLV_TopPixel , data->toppixel},
366 {TAG_DONE }
368 struct opUpdate opu;
370 opu.MethodID = OM_NOTIFY;
371 opu.opu_AttrList = tags;
372 opu.opu_GInfo = gi;
373 opu.opu_Flags = flags;
375 D(bug("asl listview notify top: top = %d\n", data->top));
377 DoSuperMethodA(cl, o, (Msg)&opu);
381 /***********************************************************************************/
383 IPTR AslListView__OM_SET(Class * cl, Object * o, struct opSet * msg)
385 struct AslListViewData *data = INST_DATA(cl, o);
386 struct TagItem *tag;
387 const struct TagItem *tstate = msg->ops_AttrList;
388 IPTR retval, tidata;
389 BOOL redraw = FALSE, notify_all = FALSE, notify_top = FALSE;
390 LONG newtop;
392 retval = DoSuperMethod(cl, o, OM_SET, (IPTR) msg->ops_AttrList, (IPTR) msg->ops_GInfo);
394 while((tag = NextTagItem(&tstate)))
396 tidata = tag->ti_Data;
398 switch(tag->ti_Tag)
400 case ASLLV_Top:
401 tidata *= data->lineheight;
402 /* fall through */
404 case ASLLV_TopPixel:
405 newtop = tidata;
406 if (newtop + data->visiblepixels > data->totalpixels)
408 newtop = data->totalpixels - data->visiblepixels;
410 if (newtop < 0) newtop = 0;
412 if (newtop != data->toppixel)
414 data->scroll = redraw ? 0 : newtop - data->toppixel;
415 data->top = newtop / data->lineheight;
416 data->toppixel = newtop;
417 notify_top = TRUE;
418 redraw = TRUE;
420 break;
422 case ASLLV_MakeVisible:
423 newtop = (LONG)tidata * data->lineheight;
425 if (newtop < 0)
427 newtop = 0;
429 else if (newtop >= data->totalpixels)
431 newtop = data->totalpixels - 1;
432 if (newtop < 0) newtop = 0;
435 /* No need to do anything if it is already visible */
437 if (newtop < data->toppixel)
439 /* new_top already okay */
441 data->scroll = redraw ? 0 : newtop - data->toppixel;
442 data->top = newtop / data->lineheight;
443 data->toppixel = newtop;
444 notify_top = TRUE;
445 redraw = TRUE;
447 else if (newtop > data->toppixel + data->visiblepixels - data->lineheight)
449 newtop -= (data->visiblepixels - data->lineheight);
450 data->scroll = redraw ? 0 : newtop - data->toppixel;
451 data->top = newtop / data->lineheight;
452 data->toppixel = newtop;
453 notify_top = TRUE;
454 redraw = TRUE;
456 break;
458 case ASLLV_Active:
460 struct Node *node;
461 WORD n = 0;
462 WORD old_active = data->active;
464 data->active = (WORD)tidata;
466 if (data->domultiselect)
468 ForeachNode(data->labels, node)
470 if (IS_MULTISEL(node) && IS_SELECTED(node) && (n != data->active))
472 MARK_UNSELECTED(node);
473 rendersingleitem(cl, o, msg->ops_GInfo, n);
475 n++;
477 } else {
478 if ((node = findnode(cl, o, old_active)))
480 MARK_UNSELECTED(node);
481 rendersingleitem(cl, o, msg->ops_GInfo, old_active);
485 if ((node = findnode(cl, o, data->active)))
487 if (!data->domultiselect || IS_MULTISEL(node))
489 MARK_SELECTED(node);
490 rendersingleitem(cl, o, msg->ops_GInfo, data->active);
495 break;
497 case ASLLV_Labels:
498 data->labels = tidata ? (struct List *)tidata : &data->emptylist;
499 data->total = CountNodes(data->labels, 0);
500 data->totalpixels = data->total * data->lineheight;
501 data->active = -1;
503 if (!data->layouted)
505 data->visible = data->total;
506 data->visiblepixels = data->visible * data->lineheight;
509 if (data->toppixel + data->visiblepixels > data->totalpixels)
511 data->toppixel = data->totalpixels - data->visiblepixels;
513 if (data->toppixel < 0) data->toppixel = 0;
514 data->top = data->toppixel / data->lineheight;
516 if (!data->layouted)
518 data->visiblepixels = data->totalpixels;
519 data->visible = data->total;
522 makenodetable(cl, o);
524 notify_all = TRUE;
525 redraw = TRUE;
526 break;
528 case ASLLV_DoMultiSelect:
529 data->domultiselect = tidata ? TRUE : FALSE;
530 break;
532 case ASLLV_ReadOnly:
533 data->readonly = tidata ? TRUE : FALSE;
534 break;
536 case ASLLV_Font:
537 data->font = (struct TextFont *)tidata;
538 break;
540 } /* switch(tag->ti_Tag) */
542 } /* while((tag = NextTagItem(&tsate))) */
544 if (redraw)
546 struct RastPort *rp;
547 struct gpRender gpr;
549 if ((rp = ObtainGIRPort(msg->ops_GInfo)))
551 gpr.MethodID = GM_RENDER;
552 gpr.gpr_GInfo = msg->ops_GInfo;
553 gpr.gpr_RPort = rp;
554 gpr.gpr_Redraw = GREDRAW_UPDATE;
556 DoMethodA(o, (Msg)&gpr);
558 ReleaseGIRPort(rp);
562 if (notify_all)
564 notifyall(cl, o, msg->ops_GInfo, 0);
566 else if (notify_top)
568 notifytop(cl, o, msg->ops_GInfo, 0);
571 return retval;
574 /***********************************************************************************/
576 IPTR AslListView__OM_NEW(Class * cl, Object * o, struct opSet * msg)
578 struct AslListViewData *data;
579 struct TagItem fitags[] =
581 {IA_FrameType, FRAME_BUTTON},
582 {IA_EdgesOnly, TRUE },
583 {TAG_DONE, 0UL}
586 struct Gadget *g = (struct Gadget *)DoSuperMethodA(cl, o, (Msg)msg);
587 if (g)
589 data = INST_DATA(cl, g);
591 /* We want to get a GM_LAYOUT message, no matter if gadget is GFLG_RELRIGHT/RELBOTTOM/
592 RELWIDTH/RELHEIGHT or not */
593 g->Flags |= GFLG_RELSPECIAL;
595 data->frame = NewObjectA(NULL, FRAMEICLASS, fitags);
596 data->ld = (struct LayoutData *)GetTagData(GA_UserData, 0, msg->ops_AttrList);
598 if (!data->ld || !data->frame)
600 CoerceMethod(cl, (Object *)g, OM_DISPOSE);
601 g = NULL;
603 else
605 data->itemheight = GetTagData(ASLLV_ItemHeight, data->ld->ld_Font->tf_YSize, msg->ops_AttrList);
606 data->spacing = GetTagData(ASLLV_Spacing, BORDERLVITEMSPACINGY * 2, msg->ops_AttrList);
608 data->lineheight = data->itemheight + data->spacing;
610 NEWLIST(&data->emptylist);
611 data->labels = &data->emptylist;
612 data->active = -1;
613 data->rendersingleitem = -1;
615 data->renderhook = (struct Hook *)GetTagData(ASLLV_CallBack, 0, msg->ops_AttrList);
616 data->default_renderhook.h_Entry = (APTR) AROS_ASMSYMNAME(ASLLVRenderHook);
617 data->default_renderhook.h_SubEntry = NULL;
618 data->default_renderhook.h_Data = (APTR)AslBase;
619 if (!data->renderhook) data->renderhook = &data->default_renderhook;
621 AslListView__OM_SET(cl, (Object *)g, msg);
625 return (IPTR)g;
628 /***********************************************************************************/
630 IPTR AslListView__OM_GET(Class * cl, Object * o, struct opGet *msg)
632 struct AslListViewData *data;
633 IPTR retval = 1;
635 data = INST_DATA(cl, o);
637 switch(msg->opg_AttrID)
639 case ASLLV_Active:
640 *msg->opg_Storage = data->active;
641 break;
643 case ASLLV_Top:
644 *msg->opg_Storage = data->top;
645 break;
647 case ASLLV_TopPixel:
648 *msg->opg_Storage = data->toppixel;
649 break;
651 case ASLLV_Total:
652 *msg->opg_Storage = data->total;
653 break;
655 case ASLLV_TotalPixels:
656 *msg->opg_Storage = data->totalpixels;
657 break;
659 case ASLLV_Visible:
660 *msg->opg_Storage = data->visible;
661 break;
663 case ASLLV_VisiblePixels:
664 *msg->opg_Storage = data->visiblepixels;
665 break;
667 default:
668 retval = DoSuperMethodA(cl, o, (Msg)msg);
669 break;
671 } /* switch(msg->opg_AttrID) */
673 return retval;
676 /***********************************************************************************/
678 IPTR AslListView__OM_DISPOSE(Class * cl, Object * o, Msg msg)
680 struct AslListViewData *data;
681 IPTR retval;
683 data = INST_DATA(cl, o);
684 if (data->frame) DisposeObject(data->frame);
685 if (data->nodetable) FreeVec(data->nodetable);
686 retval = DoSuperMethodA(cl, o, msg);
688 return retval;
691 /***********************************************************************************/
693 IPTR AslListView__GM_GOACTIVE(Class *cl, Object *o, struct gpInput *msg)
695 struct AslListViewData *data;
696 WORD i;
697 IPTR retval = GMR_NOREUSE;
699 data = INST_DATA(cl, o);
700 if ((data->total < 1) || (data->readonly)) return retval;
702 i = mouseitem(cl, o, msg->gpi_Mouse.X, msg->gpi_Mouse.Y);
704 if (i >= 0)
706 struct Node *node;
708 if ((node = findnode(cl, o, i)))
710 ULONG sec, micro;
712 CurrentTime(&sec, &micro);
714 if (data->domultiselect && IS_MULTISEL(node) &&
715 (msg->gpi_IEvent->ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
717 data->multiselecting = TRUE;
719 else
721 data->multiselecting = FALSE;
723 if (data->domultiselect)
725 struct Node *node;
726 WORD n = 0;
728 ForeachNode(data->labels, node)
730 if (IS_MULTISEL(node) && IS_SELECTED(node) && (n != data->active))
732 MARK_UNSELECTED(node);
733 rendersingleitem(cl, o, msg->gpi_GInfo, n);
735 n++;
740 data->doubleclicked = FALSE;
741 if (data->active == i)
743 if (DoubleClick(data->clicksec, data->clickmicro, sec, micro))
745 data->doubleclicked = TRUE;
748 else
750 if (!data->multiselecting && (data->active >= 0))
752 struct Node *oldnode = findnode(cl, o, data->active);
754 MARK_UNSELECTED(oldnode);
755 rendersingleitem(cl, o, msg->gpi_GInfo, data->active);
758 MARK_SELECTED(node);
759 rendersingleitem(cl, o, msg->gpi_GInfo, i);
761 data->active = i;
763 } /* if (data->active != i) */
765 data->clicksec = sec;
766 data->clickmicro = micro;
768 retval = GMR_MEACTIVE;
770 } /* if ((node = findnode(cl, o, i))) */
772 } /* if (i >= 0) */
774 return retval;
777 /***********************************************************************************/
779 IPTR AslListView__GM_HANDLEINPUT(Class *cl, Object *o, struct gpInput *msg)
781 struct AslListViewData *data;
782 UWORD code;
783 IPTR retval = GMR_MEACTIVE;
785 data = INST_DATA(cl, o);
787 switch(msg->gpi_IEvent->ie_Class)
789 case IECLASS_TIMER:
790 code = IECODE_NOBUTTON;
791 /* fall through */
793 case IECLASS_RAWMOUSE:
794 code = msg->gpi_IEvent->ie_Code;
796 switch(code)
798 case SELECTUP:
799 *msg->gpi_Termination = data->doubleclicked;
800 retval = GMR_VERIFY | GMR_NOREUSE;
801 break;
803 case IECODE_NOBUTTON:
805 WORD n = mouseitem(cl, o, msg->gpi_Mouse.X, msg->gpi_Mouse.Y);
807 if ((n == -1) && (data->active > 0)) n = data->active - 1;
808 if ((n == -2) && (data->active < data->total - 1)) n = data->active + 1;
810 if ((n >= 0) && (n != data->active))
812 struct Node *old = findnode(cl, o, data->active);
813 struct Node *new = findnode(cl, o, n);
815 if (data->multiselecting && new)
817 if (!IS_MULTISEL(new)) new = NULL;
820 if (new && old)
822 if (!data->multiselecting)
824 MARK_UNSELECTED(old);
825 rendersingleitem(cl, o, msg->gpi_GInfo, data->active);
828 MARK_SELECTED(new);
829 rendersingleitem(cl, o, msg->gpi_GInfo, n);
831 data->active = n;
834 if ((n * data->lineheight < data->toppixel) ||
835 (n * data->lineheight > data->toppixel + data->visiblepixels - data->lineheight))
837 struct RastPort *rp;
839 if (n * data->lineheight < data->toppixel)
841 LONG newtop = n * data->lineheight;
842 data->scroll = newtop - data->toppixel;
843 data->toppixel = newtop;
844 data->top = newtop / data->lineheight;
846 else
848 LONG newtop = n * data->lineheight - (data->visiblepixels - data->lineheight);
850 data->scroll = newtop - data->toppixel;
851 data->toppixel = newtop;
852 data->top = newtop / data->lineheight;
855 if ((rp = ObtainGIRPort(msg->gpi_GInfo)))
857 struct gpRender gpr;
859 gpr.MethodID = GM_RENDER;
860 gpr.gpr_GInfo = msg->gpi_GInfo;
861 gpr.gpr_RPort = rp;
862 gpr.gpr_Redraw = GREDRAW_UPDATE;
864 DoMethodA(o, (Msg)&gpr);
866 ReleaseGIRPort(rp);
869 notifytop(cl, o, msg->gpi_GInfo, OPUF_INTERIM);
871 } /* if ((n < data->top) || (n >= data->top + data->visible)) */
873 } /* if ((n >= 0) && (n != data->active)) */
874 break;
877 } /* switch(msg->gpi_IEvent->ie_Code) */
878 break;
880 } /* switch(msg->gpi_IEvent->ie_Class) */
882 return retval;
885 /***********************************************************************************/
887 IPTR AslListView__GM_LAYOUT(Class *cl, struct Gadget *g, struct gpLayout *msg)
889 struct AslListViewData *data;
890 IPTR retval = 0;
892 data = INST_DATA(cl, g);
894 if (msg->gpl_GInfo)
896 LONG newtop = data->toppixel;
897 LONG newvisible = data->visiblepixels;
899 getgadgetcoords(g, msg->gpl_GInfo, &data->minx, &data->miny, &data->width, &data->height);
901 data->maxx = data->minx + data->width - 1;
902 data->maxy = data->miny + data->height - 1;
904 newvisible = (data->height - BORDERLVSPACINGY * 2);
905 if (newtop + newvisible > data->totalpixels)
907 newtop = data->totalpixels - newvisible;
909 if (newtop < 0) newtop = 0;
911 if ((newtop != data->toppixel) || (newvisible != data->visiblepixels) || (!data->layouted))
913 data->toppixel = newtop;
914 data->top = newtop / data->lineheight;
915 data->visiblepixels = newvisible;
916 data->visible = newvisible / data->lineheight;
918 notifyall(cl, (Object *)g, msg->gpl_GInfo, 0);
921 data->layouted = TRUE;
923 retval = 1;
926 return retval;
929 /***********************************************************************************/
931 IPTR AslListView__GM_RENDER(Class *cl, Object *o, struct gpRender *msg)
933 struct AslListViewData *data;
934 struct Region *clip, *oldclip;
935 BOOL updating;
936 IPTR retval = 0;
938 data = INST_DATA(cl, o);
940 if (msg->gpr_Redraw == GREDRAW_REDRAW)
942 struct TagItem im_tags[] =
944 {IA_Width , data->width },
945 {IA_Height , data->height },
946 {IA_Recessed , data->readonly },
947 {TAG_DONE }
950 SetAttrsA(data->frame, im_tags);
952 DrawImageState(msg->gpr_RPort,
953 (struct Image *)data->frame,
954 data->minx,
955 data->miny,
956 IDS_NORMAL,
957 msg->gpr_GInfo->gi_DrInfo);
958 #if AVOID_FLICKER
960 struct IBox ibox, fbox;
962 fbox.Left = data->minx;
963 fbox.Top = data->miny;
964 fbox.Width = data->maxx - data->minx + 1;
965 fbox.Height = data->maxy - data->miny + 1;
967 ibox.Left = data->minx + BORDERLVSPACINGX;
968 ibox.Top = data->miny + BORDERLVSPACINGY;
969 ibox.Width = (data->maxx - data->minx + 1) - BORDERLVSPACINGX * 2;
970 ibox.Height = (data->maxy - data->miny + 1) - BORDERLVSPACINGY * 2;
972 PaintInnerFrame(msg->gpr_RPort,
973 msg->gpr_GInfo->gi_DrInfo,
974 data->frame,
975 &fbox,
976 &ibox,
977 msg->gpr_GInfo->gi_DrInfo->dri_Pens[BACKGROUNDPEN],
978 AslBase);
982 #endif
986 if ((clip = NewRectRegion(data->minx + BORDERLVSPACINGX,
987 data->miny + BORDERLVSPACINGY,
988 data->maxx - BORDERLVSPACINGX,
989 data->maxy - BORDERLVSPACINGY)))
991 struct Layer *lay = msg->gpr_GInfo->gi_Layer;
993 updating = (lay->Flags & LAYERUPDATING) != 0;
995 if (updating) EndUpdate(lay, FALSE);
996 oldclip = InstallClipRegion(lay, clip);
997 if (updating) BeginUpdate(lay);
1000 if (msg->gpr_Redraw == GREDRAW_REDRAW)
1002 renderallitems(cl, o, msg->gpr_RPort);
1004 } /* if (msg->gpr_Redraw == GREDRAW_REDRAW) */
1005 else if (msg->gpr_Redraw == GREDRAW_UPDATE)
1007 if (data->rendersingleitem == -1)
1009 WORD abs_scroll = (data->scroll >= 0) ? data->scroll : -data->scroll;
1011 if ((abs_scroll == 0) || (abs_scroll > data->visiblepixels / 2))
1013 renderallitems(cl, o, msg->gpr_RPort);
1015 else
1017 struct Rectangle rect;
1018 WORD scrollx1 = data->minx + BORDERLVSPACINGX;
1019 WORD scrolly1 = data->miny + BORDERLVSPACINGY;
1020 WORD scrollx2 = data->maxx - BORDERLVSPACINGX;
1021 WORD scrolly2 = data->maxy - BORDERLVSPACINGY;
1022 BOOL mustrefresh, update;
1024 ScrollRaster(msg->gpr_RPort, 0, data->scroll,
1025 scrollx1, scrolly1, scrollx2, scrolly2);
1027 mustrefresh = (msg->gpr_GInfo->gi_Layer->Flags & LAYERREFRESH) != 0;
1029 rect.MinX = scrollx1;
1030 rect.MaxX = scrollx2;
1032 if (data->scroll >= 0)
1034 rect.MinY = scrolly2 - abs_scroll;
1035 rect.MaxY = scrolly2;
1037 else
1039 rect.MinY = scrolly1;
1040 rect.MaxY = scrolly1 + abs_scroll;
1043 data->renderrect = &rect;
1044 renderallitems(cl, o, msg->gpr_RPort);
1045 data->renderrect = NULL;
1047 /* the LAYERUPDATING check should not be necessary,
1048 as then we should always have a GREDRAW_REDRAW,
1049 while here we are in GREDRAW_UPDATE. But just
1050 to be sure ... */
1052 if (mustrefresh && !(msg->gpr_GInfo->gi_Layer->Flags & LAYERUPDATING))
1054 if(!(update = BeginUpdate(msg->gpr_GInfo->gi_Layer)))
1056 EndUpdate(msg->gpr_GInfo->gi_Layer, FALSE);
1059 renderallitems(cl, o, msg->gpr_RPort);
1061 if(update) EndUpdate(msg->gpr_GInfo->gi_Layer, TRUE);
1066 else
1068 if (data->rendersingleitem >= data->top)
1070 struct Node *node = findnode(cl, o, data->rendersingleitem);
1072 renderitem(cl, o, node, data->rendersingleitem - data->top, msg->gpr_RPort);
1076 data->scroll = 0;
1077 data->rendersingleitem = -1;
1079 } /* if (msg->gpr_Redraw == GREDRAW_UPDATE) */
1081 if (clip)
1083 struct Layer *lay = msg->gpr_GInfo->gi_Layer;
1085 if (updating) EndUpdate(lay, FALSE);
1086 InstallClipRegion(lay, oldclip);
1087 if (updating) BeginUpdate(lay);
1089 DisposeRegion(clip);
1092 return retval;
1095 /***********************************************************************************/