1 /* $VER: ListViewDemo 1.6 (15.12.98) by Bernardo Innocenti
7 ** This program demonstrates how to use the `boopsi' ListView gadget.
9 ** The source code shows how to create a resizable window with sliders
10 ** and how to write a custom `boopsi' class on top of the gadgetclass.
16 ** This project can be compiled with SAS/C 6.58 or better and
17 ** GeekGadget's GCC 2.7.2.1 or better.
18 ** You get the smallest executable with SAS/C. GCC will give
19 ** you quite a lot of warnings with the tag calls. Don't worry about them.
25 ** 0.1 (23.6.96) First try
26 ** 1.0 (21.1.97) First alpha release
27 ** 1.1 (24.5.97) Lotsa bugs fixed, implemented LVA_DoubleClick
28 ** 1.2 (31.8.97) Lotsa bugs fixed, implemented LVA_Clipped
29 ** Fixed memory leak with the test list
30 ** 1.3 (5.9.97) Improved initial sliders notification
31 ** Added multiple selection (LVA_DoMultiselect)
32 ** Fixed scrolling problems in some unusual conditions
33 ** 1.4 (8.9.97) Sets GMORE_SCROLLRASTER in OM_NEW
34 ** Multiple demo windows showing the features of the class
35 ** 1.5 (14.9.97) Added LVA_ItemSpacing
36 ** Finally fixed the LVA_Clipped mode!
38 ** 1.6 (2.10.97) Added StormC support
39 ** Implemented pixel-wise vertical scrolling for clipped mode
40 ** Reworked the class istance data and some code
42 ** 1.7 (15.12.98) Added ListBoxClass
43 ** Moved ScrollButtonClass in its own file
44 ** Removed function OpenClass()
45 ** Updated to latest version of VectorGlyphIClass
51 ** - This code has never been tested on V37.
53 ** - Middle mouse button scrolling does not work because
54 ** of a bug in input.device V40.
60 ** Copyright © 1996,97 by Bernardo Innocenti <bernardo.innocenti@usa.net>.
61 ** Freely Distributable, as long as source code, documentation and
62 ** executable are kept together. Permission is granted to release
63 ** modified versions of this program as long as all existing copyright
64 ** notices are left intact.
68 #define USE_BUILTIN_MATH
69 #define INTUI_V36_NAMES_ONLY
71 #define CLIB_ALIB_PROTOS_H /* Avoid including this header file because of
72 * conflicting definitions in BoopsiStubs.h
74 #include <exec/types.h>
75 #include <exec/memory.h>
76 #include <exec/execbase.h>
80 #include <intuition/intuition.h>
81 #include <intuition/intuitionbase.h>
82 #include <intuition/screens.h>
83 #include <intuition/classes.h>
84 #include <intuition/gadgetclass.h>
85 #include <intuition/imageclass.h>
86 #include <intuition/icclass.h>
87 #include <devices/timer.h>
89 #include <proto/exec.h>
90 #include <proto/intuition.h>
91 #include <proto/dos.h>
92 #include <proto/utility.h>
93 #include <proto/graphics.h>
94 #include <proto/diskfont.h>
101 #include "CompilerSpecific.h"
103 #include "BoopsiStubs.h"
104 #include "ListMacros.h"
106 #include "ListViewClass.h"
107 #include "ListBoxClass.h"
108 #include "VectorGlyphIClass.h"
109 #include "ScrollButtonClass.h"
114 #define WANTEDLIBVER 39L
116 #define WANTEDLIBVER 37L
120 /* Local function prototypes */
122 LONG SAVEDS main (void);
123 static struct MsgPort *OpenDemoWindows (struct List *winlist);
124 static void CloseDemoWindows (struct List *winlist);
125 static struct LVHandle *OpenLVWin (CONST_STRPTR pubscreen,
126 struct MsgPort *winport, CONST_STRPTR title, ULONG mode, BOOL useListBox,
127 ULONG left, ULONG top, ULONG width, ULONG height, ULONG moreTags, ...);
128 static void CloseLVWin (struct LVHandle *lvhandle);
129 static struct Gadget *CreateLVGadgets (struct LVHandle *lvhandle,
130 struct TagItem *moreTags);
131 static void DisposeGadgets (struct LVHandle *lvhandle);
132 static void CreateItems (struct LVHandle *lvhandle);
133 static void CreateImages (struct DrawInfo *dri);
134 static void FreeImages (void);
137 /* Width and height for the demo vector images */
138 #define IMAGES_WIDTH 56
139 #define IMAGES_HEIGHT 48
145 GAD_LV, GAD_VSLIDER, GAD_HSLIDER,
146 GAD_UPBUTTON, GAD_DOWNBUTTON, GAD_LEFTBUTTON, GAD_RIGHTBUTTON,
154 IMG_UP, IMG_DOWN, IMG_LEFT, IMG_RIGHT, IMG_COUNT
160 /* This structure describes an open ListView window */
163 struct MinNode Link; /* Link LVHandle in a list of all windows */
164 struct Window *Win; /* Pointer to our window */
165 struct Screen *Scr; /* The screen we are opening our windows on */
166 struct DrawInfo *DrawInfo; /* DrawInfo for this screen */
167 ULONG Mode; /* ListView operating mode */
168 APTR Items; /* Items attached to the ListView */
169 ULONG Total; /* Number of items or -1 if unknown */
170 struct Gadget *Gad[GAD_COUNT];/* All our gadgets */
171 APTR Model; /* Make boopsi gadgets talk to each other */
172 struct List TestList; /* Items list for LVA_#?List modes */
173 ULONG *SelectArray; /* Array for storing multiple selections */
174 BOOL UseListBox; /* If TRUE, window uses the ListBox class */
181 UBYTE versiontag[] = "$VER: ListViewDemo 1.7 (15.12.98) by Bernardo Innocenti"
182 " (compiled with " _COMPILED_WITH ")";
186 /* Workaround a bug in StormC header file <proto/utility.h> */
189 #define UTILITYBASETYPE struct Library
191 #define UTILITYBASETYPE struct UtilityBase
195 struct ExecBase *SysBase;
196 UTILITYBASETYPE *UtilityBase;
197 struct IntuitionBase *IntuitionBase;
198 struct GfxBase *GfxBase;
199 struct Library *LayersBase;
200 struct Library *DiskfontBase;
203 /* Our private `boopsi' classes */
204 Class *ListViewClass;
205 static Class *ListBoxClass;
206 static Class *ScrollButtonClass;
209 /* `boopsi' images for all windows
211 * These variables must be NULL at startup time. We are not
212 * going to explicitly initialize them because otherwise
213 * Storm C 2.0 would generate a C++-style constructor to
214 * do it :-). LoasSeg() will clear the BSS data section
215 * for us, so these variables are guaranteed to be NULL anyway.
217 static struct Image *Img[IMG_COUNT];
218 static ULONG ImgWidth[IMG_COUNT];
219 static ULONG ImgHeight[IMG_COUNT];
220 static struct TextFont *CustomFont;
224 /* Attribute translations for object interconnections */
226 static LONG MapLVToHSlider[] =
228 LVA_PixelLeft, PGA_Top,
229 LVA_PixelWidth, PGA_Total,
230 LVA_PixelHVisible, PGA_Visible,
234 static LONG MapHSliderToLV[] =
236 PGA_Top, LVA_PixelLeft,
241 static LONG MapLVToVSlider[] =
244 LVA_Total, PGA_Total,
245 LVA_Visible, PGA_Visible,
250 static LONG MapLVToVSlider[] =
252 LVA_PixelTop, PGA_Top,
253 LVA_PixelHeight, PGA_Total,
254 LVA_PixelVVisible, PGA_Visible,
260 static LONG MapVSliderToLV[] =
267 static LONG MapVSliderToLV[] =
269 PGA_Top, LVA_PixelTop,
275 static LONG MapUpButtonToLV[] =
281 static LONG MapDownButtonToLV[] =
287 static LONG MapLeftButtonToLV[] =
293 static LONG MapRightButtonToLV[] =
295 GA_ID, LVA_MoveRight,
303 /* StormC does not see that the expression "versiontag + 6" is constant
304 * and generates an initializer for it. The following definition
305 * works around this problem.
308 #define VERSIONTAG "ListViewDemo 1.7 by Bernardo Innocenti (compiled with " _COMPILED_WITH ")"
310 #define VERSIONTAG versiontag + 6
313 static STRPTR TestStrings[] =
317 "This `boopsi' ListView class supports all the features",
318 "of the Gadtools LISTVIEW_KIND, plus more stuff:",
320 " + Easy to use (almost a drop-in replacement for LISTVIEW_KIND)",
321 " + Can be resized and supports GREL_#? flags",
322 " + Multiple selection of items",
323 " + Notifies your `boopsi' sliders",
324 " + Multiple columns (TODO)",
325 " + Redraws quickly without clearing (which is good for solid window sizing)",
326 " + Horizontal scrolling (TODO)",
327 " + Items with `boopsi' images",
328 " + Using arrays instead of exec lists",
329 " + You can use `boopsi' label images instead of plain text",
330 " + You can use your own custom rendering hook",
331 " + You can use your own item item-retriving callback hook",
332 " + List title (TODO)",
333 " + Full Keyboard control (all control, alt and shift key combinations supported)",
334 " + Asynchronous scrolling with inertia (TODO)",
335 " + OS 3.0 optimized (V39-only version also available)",
336 " + RTG friendly and optimized (no planar stuff in chunky bitmaps)",
337 " + Small code! (<10K)",
338 " + Written in C to be highly portable across compilers and CPUs",
339 " + Full commented source code included",
340 " + Source code compiles with SAS/C, StormC and GCC",
341 " + Subclasses can be easlily derived from the base listview class",
343 "Please send comments to <bernardo.innocenti@usa.net>."
346 #define TESTSTRINGS_CNT (sizeof (TestStrings) / sizeof (CONST_STRPTR))
350 LONG SAVEDS _main (void)
352 /* Main program entry point. When linking without startup code, this
353 * must be the first function in the first object module listed on the
354 * linker command line. We also need to initialize SysBase and open
355 * all needed libraries manually.
358 struct MinList winlist;
359 struct MsgPort *winport;
360 struct Library *VectorGlyphBase = NULL;
361 LONG sigwait, sigrcvd;
362 LONG retval = RETURN_FAIL; /* = RETURN_FAIL */
366 /* Initialize SysBase */
367 SysBase = *((struct ExecBase **)4UL);
369 /* Open system libraries */
371 if ((UtilityBase = (UTILITYBASETYPE *) OpenLibrary ("utility.library", 37L)) &&
372 (IntuitionBase = (struct IntuitionBase *)OpenLibrary ("intuition.library", WANTEDLIBVER)) &&
373 (GfxBase = (struct GfxBase *)OpenLibrary ("graphics.library", WANTEDLIBVER)) &&
374 (LayersBase = OpenLibrary ("layers.library", WANTEDLIBVER)))
376 if ((ListViewClass = MakeListViewClass ()) &&
377 (ListBoxClass = MakeListBoxClass ()) &&
378 (ScrollButtonClass = MakeScrollButtonClass ()) &&
379 (VectorGlyphBase = OpenLibrary ("images/vectorglyph.image", 0)))
381 NEWLIST ((struct List *)&winlist);
383 if (winport = OpenDemoWindows ((struct List *)&winlist))
385 /* Pre-calculate the signal mask for Wait() */
386 sigwait = (1 << winport->mp_SigBit) |
389 /* Now for the main loop. As you can see, it is really
390 * very compact. That's the magic of boopsi! :-)
394 /* Sleep until something interesting occurs */
395 sigrcvd = Wait (sigwait);
397 /* Now handle received signals */
400 if (sigrcvd & SIGBREAKF_CTRL_C)
404 if (sigrcvd & (1 << winport->mp_SigBit))
406 struct IntuiMessage *msg;
408 while (msg = (struct IntuiMessage *) GetMsg (winport))
412 case IDCMP_CLOSEWINDOW:
419 ReplyMsg ((struct Message *) msg);
422 } /* End while (!quit) */
424 retval = 0; /* RETURN_OK */
426 CloseDemoWindows ((struct List *)&winlist);
432 /* These cannot fail. Passing NULL is ok. */
433 CloseLibrary ((struct Library *)VectorGlyphBase);
434 FreeScrollButtonClass (ScrollButtonClass);
435 FreeListBoxClass (ListBoxClass);
436 FreeListViewClass (ListViewClass);
439 /* Passing NULL to CloseLibrary() was illegal in pre-V37 Exec.
440 * To avoid crashing when someone attempts to run this program
441 * on an old OS, we need to test the first library base we tried
446 CloseLibrary ((struct Library *)LayersBase);
447 CloseLibrary ((struct Library *)GfxBase);
448 CloseLibrary ((struct Library *)IntuitionBase);
449 CloseLibrary ((struct Library *)UtilityBase);
457 static struct MsgPort *OpenDemoWindows (struct List *winlist)
459 struct LVHandle *lvhandle;
460 struct MsgPort *winport;
462 if (DiskfontBase = OpenLibrary ("diskfont.library", 0L))
464 static struct TextAttr attr =
472 CustomFont = OpenDiskFont (&attr);
473 CloseLibrary (DiskfontBase);
476 /* Setup windows shared Message Port */
477 if (winport = CreateMsgPort())
479 if (lvhandle = OpenLVWin (NULL, winport,
481 LVA_StringList, TRUE, 600, 20, 320, 128,
483 ADDTAIL (winlist, (struct Node *)lvhandle);
485 if (lvhandle = OpenLVWin (NULL, winport,
486 "LVA_TextFont = times/24/italic, LVA_Clipped = TRUE",
487 LVA_StringList, FALSE, 320, 320, 320, 64,
488 LVA_TextFont, CustomFont,
491 ADDTAIL (winlist, (struct Node *)lvhandle);
493 if (lvhandle = OpenLVWin (NULL, winport,
494 "LAYOUTA_Spacing = 4",
495 LVA_StringList, FALSE, 256, 256, 320, 64,
498 ADDTAIL (winlist, (struct Node *)lvhandle);
500 if (lvhandle = OpenLVWin (NULL, winport,
501 "GA_ReadOnly = TRUE; LVA_Selected = 3",
502 LVA_StringList, FALSE, 192, 192, 320, 64,
506 ADDTAIL (winlist, (struct Node *)lvhandle);
508 if (lvhandle = OpenLVWin (NULL, winport,
509 "Single selection image list, LVA_Clipped = TRUE",
510 LVA_ImageList, FALSE, 128, 128, 320, 128,
511 LVA_ItemHeight, IMAGES_HEIGHT,
514 ADDTAIL (winlist, (struct Node *)lvhandle);
516 if (lvhandle = OpenLVWin (NULL, winport,
517 "LVA_DoMultiSelect = TRUE; LVA_StringArray",
518 LVA_StringArray, FALSE, 64, 64, 320, 128,
519 LVA_DoMultiSelect, TRUE,
521 ADDTAIL (winlist, (struct Node *)lvhandle);
523 if (lvhandle = OpenLVWin (NULL, winport,
524 "Plain, single selection string list",
525 LVA_StringList, FALSE, 0, 20, 320, 128,
527 ADDTAIL (winlist, (struct Node *)lvhandle);
529 /* Abort only if no windows could be opened */
530 if (IsListEmpty (winlist))
532 DeleteMsgPort (winport);
533 CloseFont (CustomFont);
543 static void CloseDemoWindows (struct List *winlist)
545 struct MsgPort *winport = NULL;
546 struct LVHandle *lvhandle;
548 while (lvhandle = (struct LVHandle *) REMHEAD (winlist))
550 /* Safe way to close a shared IDCMP port window */
557 winport = lvhandle->Win->UserPort;
558 msg = (struct Message *) winport->mp_MsgList.lh_Head;
560 /* Now remove any pending message from the shared IDCMP port */
561 while (succ = msg->mn_Node.ln_Succ)
563 /* Since we are closing all our windows at once,
564 * we don't need to check to which window this
565 * message was addressed.
567 REMOVE ((struct Node *)msg);
569 msg = (struct Message *) succ;
572 /* Keep intuition from freeing our port... */
573 lvhandle->Win->UserPort = NULL;
575 /* ...and from sending us any more messages. */
576 ModifyIDCMP (lvhandle->Win, 0L);
580 CloseLVWin (lvhandle);
583 DeleteMsgPort (winport); /* NULL is ok */
586 CloseFont (CustomFont);
591 /* No-op backfilling hook. Since we are going to redraw the whole window
592 * anyway, we can disable backfilling. This avoids ugly flashing while
593 * resizing or revealing the window.
595 * This function does not need the __saveds attribute because it makes no
596 * references to external data.
601 static ULONG BFHookFunc (void)
603 return 1; /* Do nothing */
606 static struct Hook BFHook =
609 (ULONG(*)())BFHookFunc,
612 #endif /* !OS30_ONLY */
616 static struct LVHandle *OpenLVWin (CONST_STRPTR pubscreen,
617 struct MsgPort *winport, CONST_STRPTR title, ULONG mode, BOOL useListBox,
618 ULONG left, ULONG top, ULONG width, ULONG height, ULONG moreTags, ...)
620 struct LVHandle *lvhandle;
621 struct Gadget *glist;
623 if (lvhandle = AllocMem (sizeof (struct LVHandle), MEMF_ANY | MEMF_CLEAR))
625 if (lvhandle->Scr = LockPubScreen (pubscreen))
627 /* GetScreenDrawInfo() never fails */
628 lvhandle->DrawInfo = GetScreenDrawInfo (lvhandle->Scr);
630 /* Set listview operating mode and ListBox flag */
631 lvhandle->Mode = mode;
632 lvhandle->UseListBox = useListBox;
634 CreateItems (lvhandle);
636 if (glist = CreateLVGadgets (lvhandle, (struct TagItem *)&moreTags))
639 /* I'm using this define because GCC does not support putting
640 * preprocessor directives (#ifdef/#endif) inside macro arguments.
643 #define BACKFILL_TAG_VALUE ((IntuitionBase->LibNode.lib_Version < 39) ? &BFHook : LAYERS_NOBACKFILL)
645 #define BACKFILL_TAG_VALUE LAYERS_NOBACKFILL
646 #endif /* !OS30_ONLY */
648 if (lvhandle->Win = OpenWindowTags (NULL,
651 WA_InnerWidth, width,
652 WA_InnerHeight, height,
653 WA_PubScreen, lvhandle->Scr,
656 WA_BackFill, useListBox ? NULL : BACKFILL_TAG_VALUE,
657 WA_ScreenTitle, versiontag + 6,
658 WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_SIZEGADGET | WFLG_SIZEBRIGHT | WFLG_SIZEBBOTTOM |
659 WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH | WFLG_NOCAREREFRESH,
660 WA_PubScreenFallBack, TRUE,
667 #undef BACKFILL_TAG_VALUE
669 lvhandle->Win->UserPort = winport;
670 ModifyIDCMP (lvhandle->Win, IDCMP_CLOSEWINDOW);
672 /* We need to keep our screen locked all the time
673 * because we want to free the associated DrawInfo
674 * *after* the window has been closed and
675 * FreeScreenDrawInfo() wants a pointer to a *valid*
681 DisposeGadgets (lvhandle);
684 FreeScreenDrawInfo (lvhandle->Scr, lvhandle->DrawInfo);
685 /* lvhandle->DrawInfo = NULL */
687 UnlockPubScreen (NULL, lvhandle->Scr);
689 FreeMem (lvhandle, sizeof (struct LVHandle));
696 static void CloseLVWin (struct LVHandle *lvhandle)
698 /* Close our window. No need to reply queued messages,
699 * Intuition is clever enough to care about this for us.
701 CloseWindow (lvhandle->Win);
702 DisposeGadgets (lvhandle);
703 UnlockPubScreen (NULL, lvhandle->Scr);
705 FreeVec (lvhandle->SelectArray); /* NULL is ok */
707 if ((lvhandle->Mode == LVA_StringList) || (lvhandle->Mode == LVA_ImageList))
711 /* Free the test list */
712 while (node = REMHEAD (&lvhandle->TestList))
714 if (lvhandle->Mode == LVA_ImageList)
715 DisposeObject ((Object *)node->ln_Name);
716 FreeMem (node, sizeof (struct Node));
720 FreeMem (lvhandle, sizeof (struct LVHandle));
725 /* Diagram of object interconnections for the ListView window
726 * ==========================================================
728 * ScrollButtonClass objects
729 * +----------+ +------------+ +------------+ +-------------+
730 * | UpButton | | DownButton | | LeftButton | | RightButton |
731 * +----------+ +------------+ +------------+ +-------------+
732 * | GA_ID = | GA_ID = | GA_ID = | GA_ID =
733 * | LVA_MoveUp | LVA_MoveDown | LVA_MoveLeft | LVA_MoveRight
736 * | | +-----------------------+ |
737 * | | | +------------------------------------+
738 * | | | | propgclass object icclass object
739 * | | | | +-----------+ +--------------+
740 * | | | | | HSlider |<-----| PIPToHSlider |
741 * | | | | +-----------+ +--------------+
742 * | | | | PGA_Top = | ^ LVA_Top = PGA_Top
743 * | | | | LVA_Left | | LVA_Visible = PGA_Visible
746 * +-----------+ *********** |
747 * | |-------->* *------------+
748 * | ListView | * Model *
749 * | |<--------* *------------+
750 * +-----------+ *********** |
753 * LVA_Top | V icclass object
754 * +-----------+ +--------------+
755 * | VSlider |<-----| PIPToVSlider |
756 * +-----------+ +--------------+
757 * propgclass object LVA_Top = PGA_Top
758 * LVA_Visible = PGA_Visible
761 static struct Gadget *CreateLVGadgets (struct LVHandle *lvhandle,
762 struct TagItem *moreTags)
764 struct Screen *scr = lvhandle->Scr;
765 ULONG SizeWidth = 18, SizeHeight = 11; /* Default size */
766 struct Image *SizeImage;
768 /* Create a size image to get its... uhm... size */
769 if (SizeImage = NewObject (NULL, SYSICLASS,
770 SYSIA_Which, SIZEIMAGE,
771 SYSIA_DrawInfo, lvhandle->DrawInfo,
774 /* Get size gadget geometry */
775 GetAttr (IA_Width, SizeImage, &SizeWidth);
776 GetAttr (IA_Height, SizeImage, &SizeHeight);
778 /* And then get rid of it... */
779 DisposeObject (SizeImage);
783 if (lvhandle->UseListBox)
785 lvhandle->Gad[GAD_LV] = NewObject (ListBoxClass, NULL,
787 GA_Left, scr->WBorLeft,
788 GA_Top, scr->WBorTop + scr->Font->ta_YSize + 1,
789 GA_RelWidth, - SizeWidth - scr->WBorLeft,
790 GA_RelHeight, - (scr->WBorTop + scr->Font->ta_YSize + SizeHeight + 1),
791 GA_DrawInfo, lvhandle->DrawInfo,
792 lvhandle->Mode, lvhandle->Items,
793 LVA_Total, lvhandle->Total,
794 LVA_SelectArray, lvhandle->SelectArray,
797 return lvhandle->Gad[GAD_LV];
800 /* Code to create normal ListView class and its gadgets */
803 /* No need to check this: in case of failure we would just
804 * get no images in the scroll buttons, but we can still try
805 * to open our window.
807 CreateImages (lvhandle->DrawInfo);
809 if (lvhandle->Model = NewObjectA (NULL, MODELCLASS, NULL))
810 if (lvhandle->Gad[GAD_LV] = NewObject (ListViewClass, NULL,
812 GA_Left, scr->WBorLeft,
813 GA_Top, scr->WBorTop + scr->Font->ta_YSize + 1,
814 GA_RelWidth, - SizeWidth - scr->WBorLeft,
815 GA_RelHeight, - (scr->WBorTop + scr->Font->ta_YSize + SizeHeight + 1),
816 GA_DrawInfo, lvhandle->DrawInfo,
817 ICA_TARGET, lvhandle->Model,
818 lvhandle->Mode, lvhandle->Items,
819 LVA_Total, lvhandle->Total,
820 LVA_SelectArray, lvhandle->SelectArray,
822 if (lvhandle->Gad[GAD_VSLIDER] = NewObject (NULL, PROPGCLASS,
824 GA_Previous, lvhandle->Gad[GAD_LV],
825 GA_RelRight, - SizeWidth + 5,
826 GA_Top, scr->WBorTop + scr->Font->ta_YSize + 2,
827 GA_Width, SizeWidth - 8,
828 GA_RelHeight, - (scr->WBorTop + scr->Font->ta_YSize +
829 SizeHeight + ImgHeight[IMG_DOWN] + ImgHeight[IMG_UP] + 4),
830 GA_RightBorder, TRUE,
831 GA_DrawInfo, lvhandle->DrawInfo,
832 PGA_Freedom, FREEVERT,
833 PGA_Borderless, ((lvhandle->DrawInfo->dri_Flags & DRIF_NEWLOOK) &&
834 (lvhandle->DrawInfo->dri_Depth != 1)),
836 ICA_TARGET, lvhandle->Model,
837 ICA_MAP, MapVSliderToLV,
839 if (lvhandle->Gad[GAD_HSLIDER] = NewObject (NULL, PROPGCLASS,
841 GA_Previous, lvhandle->Gad[GAD_VSLIDER],
842 GA_RelBottom, - SizeHeight + ((SizeHeight > 15) ? 4 : 3),
843 GA_Left, scr->WBorLeft,
844 GA_Height, SizeHeight - ((SizeHeight > 15) ? 6 : 4),
845 GA_RelWidth, - (SizeWidth + ImgWidth[IMG_RIGHT] + ImgWidth[IMG_LEFT] + scr->WBorLeft + 2),
846 GA_BottomBorder,TRUE,
847 GA_DrawInfo, lvhandle->DrawInfo,
848 PGA_Freedom, FREEHORIZ,
849 PGA_Borderless, ((lvhandle->DrawInfo->dri_Flags & DRIF_NEWLOOK) &&
850 (lvhandle->DrawInfo->dri_Depth != 1)),
852 ICA_TARGET, lvhandle->Model,
853 ICA_MAP, MapHSliderToLV,
855 if (lvhandle->Gad[GAD_UPBUTTON] = NewObject (ScrollButtonClass, NULL,
857 GA_Previous, lvhandle->Gad[GAD_HSLIDER],
858 GA_RelBottom, - SizeHeight - ImgHeight[IMG_DOWN] - ImgHeight[IMG_UP] + 1,
859 GA_RelRight, - ImgWidth[IMG_DOWN] + 1,
860 GA_RightBorder, TRUE,
861 GA_DrawInfo, lvhandle->DrawInfo,
862 GA_Image, Img[IMG_UP],
863 ICA_TARGET, lvhandle->Gad[GAD_LV],
864 ICA_MAP, MapUpButtonToLV,
866 if (lvhandle->Gad[GAD_DOWNBUTTON] = NewObject (ScrollButtonClass, NULL,
867 GA_ID, GAD_DOWNBUTTON,
868 GA_Previous, lvhandle->Gad[GAD_UPBUTTON],
869 GA_RelBottom, - SizeHeight - ImgHeight[IMG_DOWN] + 1,
870 GA_RelRight, - ImgWidth[IMG_DOWN] + 1,
871 GA_RightBorder, TRUE,
872 GA_DrawInfo, lvhandle->DrawInfo,
873 GA_Image, Img[IMG_DOWN],
874 ICA_TARGET, lvhandle->Gad[GAD_LV],
875 ICA_MAP, MapDownButtonToLV,
877 if (lvhandle->Gad[GAD_LEFTBUTTON] = NewObject (ScrollButtonClass, NULL,
878 GA_ID, GAD_LEFTBUTTON,
879 GA_Previous, lvhandle->Gad[GAD_DOWNBUTTON],
880 GA_RelBottom, - ImgHeight[IMG_LEFT] + 1,
881 GA_RelRight, - SizeWidth - ImgWidth[IMG_RIGHT] - ImgWidth[IMG_LEFT] + 1,
882 GA_BottomBorder,TRUE,
883 GA_DrawInfo, lvhandle->DrawInfo,
884 GA_Image, Img[IMG_LEFT],
885 ICA_TARGET, lvhandle->Gad[GAD_LV],
886 ICA_MAP, MapLeftButtonToLV,
888 if (lvhandle->Gad[GAD_RIGHTBUTTON] = NewObject (ScrollButtonClass, NULL,
889 GA_ID, GAD_RIGHTBUTTON,
890 GA_Previous, lvhandle->Gad[GAD_LEFTBUTTON],
891 GA_RelBottom, - ImgHeight[IMG_RIGHT] + 1,
892 GA_RelRight, - SizeWidth - ImgWidth[IMG_RIGHT] + 1,
893 GA_BottomBorder,TRUE,
894 GA_DrawInfo, lvhandle->DrawInfo,
895 GA_Image, Img[IMG_RIGHT],
896 ICA_TARGET, lvhandle->Gad[GAD_LV],
897 ICA_MAP, MapRightButtonToLV,
902 /* Connect VSlider to Model */
904 if (icobject = NewObject (NULL, ICCLASS,
905 ICA_TARGET, lvhandle->Gad[GAD_VSLIDER],
906 ICA_MAP, MapLVToVSlider,
908 if (!DoMethod (lvhandle->Model, OM_ADDMEMBER, icobject))
909 DisposeObject (icobject);
911 /* Connect HSlider to Model */
913 if (icobject = NewObject (NULL, ICCLASS,
914 ICA_TARGET, lvhandle->Gad[GAD_HSLIDER],
915 ICA_MAP, MapLVToHSlider,
917 if (!DoMethod (lvhandle->Model, OM_ADDMEMBER, icobject))
918 DisposeObject (icobject);
920 /* Connect Model to ListView */
922 SetAttrs (lvhandle->Model,
923 ICA_TARGET, lvhandle->Gad[GAD_LV],
926 return lvhandle->Gad[GAD_LV];
928 DisposeGadgets (lvhandle);
935 static void DisposeGadgets (struct LVHandle *lvhandle)
939 for (i = 0; i < GAD_COUNT; i++)
941 DisposeObject (lvhandle->Gad[i]);
942 /* lvhandle->Gad[i] = NULL; */
945 /* Freeing the Model will also free its two targets */
946 DisposeObject (lvhandle->Model);
947 /* lvhandle->Model = NULL */
952 static void CreateItems (struct LVHandle *lvhandle)
954 if ((lvhandle->Mode == LVA_StringList) || (lvhandle->Mode == LVA_ImageList))
960 if (lvhandle->Mode == LVA_StringList)
961 cnt = TESTSTRINGS_CNT;
962 else /* LVA_ImageList */
963 cnt = VG_IMGCOUNT * 8;
966 /* Build a list of nodes to test the list */
968 NEWLIST (&lvhandle->TestList);
970 for (i = 0; i < cnt; i++)
972 if (node = AllocMem (sizeof (struct Node), MEMF_PUBLIC))
974 if (lvhandle->Mode == LVA_StringList)
975 node->ln_Name = TestStrings[i];
977 node->ln_Name = (STRPTR) NewObject (NULL, VECTORGLYPHCLASS,
978 SYSIA_Which, i % VG_IMGCOUNT,
979 SYSIA_DrawInfo, lvhandle->DrawInfo,
980 IA_Width, IMAGES_WIDTH,
981 IA_Height, IMAGES_HEIGHT,
984 /* Unselect all items */
987 ADDTAIL (&lvhandle->TestList, node);
993 lvhandle->Items = &lvhandle->TestList;
995 else if (lvhandle->Mode == LVA_StringArray)
997 lvhandle->Items = TestStrings;
998 lvhandle->Total = TESTSTRINGS_CNT;
999 lvhandle->SelectArray = AllocVec (TESTSTRINGS_CNT * sizeof (ULONG),
1000 MEMF_CLEAR | MEMF_PUBLIC);
1002 else /* (lvhandle->Mode == LVA_ImageArray) */
1004 lvhandle->Items = NULL; /* No items */
1005 lvhandle->Total = -1; /* Unknown */
1011 static void CreateImages (struct DrawInfo *dri)
1013 /* Create 4 arrow images for the window scroll buttons.
1015 * Why bother checking for failure? The arrow images are not
1016 * life critical in our program...
1019 static ULONG imagetypes[IMG_COUNT] = { UPIMAGE, DOWNIMAGE, LEFTIMAGE, RIGHTIMAGE };
1022 for (i = 0; i < IMG_COUNT; i++)
1024 if (Img[i] = (struct Image *)NewObject (NULL, SYSICLASS,
1025 SYSIA_Which, imagetypes[i],
1026 SYSIA_DrawInfo, dri,
1029 /* Ask image width and height */
1030 GetAttr (IA_Width, Img[i], &ImgWidth[i]);
1031 GetAttr (IA_Height, Img[i], &ImgHeight[i]);
1037 static void FreeImages (void)
1041 for (i = 0; i < IMG_COUNT; i++)
1042 DisposeObject ((APTR)Img[i]); /* DisposeObject(NULL) is safe */