Removed the unnecessary inner group: the list and scrollbar are now
[AROS.git] / workbench / libs / muimaster / classes / listview.c
blobb77c4662e84416e9aa65288caaa44d72bb81ba82
1 /*
2 Copyright © 2002-2015, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/debug.h>
8 #include <graphics/gfx.h>
9 #include <graphics/view.h>
10 #include <devices/rawkeycodes.h>
11 #include <clib/alib_protos.h>
12 #include <proto/exec.h>
13 #include <proto/graphics.h>
14 #include <proto/utility.h>
15 #include <proto/intuition.h>
16 #include <proto/muimaster.h>
18 #include "mui.h"
19 #include "muimaster_intern.h"
20 #include "support.h"
21 #include "window.h"
22 #include "list.h"
23 #include "prefs.h"
25 extern struct Library *MUIMasterBase;
27 struct MUI_ListviewData
29 Object *list, *vert;
30 struct Hook hook;
31 struct Hook selfnotify_hook;
32 BOOL noforward;
33 BOOL read_only;
34 BOOL select_change;
35 IPTR multiselect;
36 IPTR scroller_pos;
37 struct MUI_EventHandlerNode ehn;
39 int mouse_click; /* see below if mouse is held down */
41 /* double click */
42 ULONG last_secs;
43 ULONG last_mics;
44 ULONG last_active;
45 BOOL doubleclick;
47 /* clicked column */
48 LONG click_column;
49 LONG def_click_column;
51 /* user prefs */
52 ListviewMulti prefs_multi;
55 #define MOUSE_CLICK_ENTRY 1 /* on entry clicked */
56 #define MOUSE_CLICK_TITLE 2 /* on title clicked */
58 static void DoWheelMove(struct IClass *cl, Object *obj, LONG wheely);
60 #define PROP_VERT_FIRST 1
61 #define LIST_VERT_FIRST 4
62 #define LIST_VERT_VISIBLE 5
63 #define LIST_VERT_ENTRIES 6
65 ULONG Listview_Function(struct Hook *hook, APTR dummyobj, void **msg)
67 struct MUI_ListviewData *data = (struct MUI_ListviewData *)hook->h_Data;
68 SIPTR type = (SIPTR) msg[0];
69 SIPTR val = (SIPTR) msg[1];
71 D(bug("[ListView] List 0x%p, Event %d, value %ld\n", data->list, type,
72 val));
74 switch (type)
76 case PROP_VERT_FIRST:
77 get(data->vert, MUIA_Prop_First, &val);
78 nnset(data->list, MUIA_List_VertProp_First, val);
79 break;
81 case LIST_VERT_FIRST:
82 nnset(data->vert, MUIA_Prop_First, val);
83 break;
84 case LIST_VERT_VISIBLE:
85 nnset(data->vert, MUIA_Prop_Visible, val);
86 break;
87 case LIST_VERT_ENTRIES:
88 nnset(data->vert, MUIA_Prop_Entries, val);
89 break;
91 return 0;
94 ULONG SelfNotify_Function(struct Hook *hook, APTR obj, void **msg)
96 struct MUI_ListviewData *data = (struct MUI_ListviewData *)hook->h_Data;
97 SIPTR attribute = (SIPTR) msg[0];
98 SIPTR value = (SIPTR) msg[1];
100 /* This allows avoiding notify loops */
101 data->noforward = TRUE;
102 SetAttrs(obj, MUIA_Group_Forward, FALSE, attribute, value, TAG_DONE);
103 data->noforward = FALSE;
105 return 0;
108 /**************************************************************************
109 OM_NEW
110 **************************************************************************/
111 IPTR Listview__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
113 struct MUI_ListviewData *data;
114 struct TagItem *tag, *tags;
115 Object *vert;
116 Object *list =
117 (Object *) GetTagData(MUIA_Listview_List, (IPTR) NULL,
118 msg->ops_AttrList);
119 LONG entries = 0, first = 0, visible = 0;
121 if (!list)
122 return (IPTR) NULL;
124 vert = ScrollbarObject, MUIA_Group_Horiz, FALSE, End;
126 obj = (Object *) DoSuperNewTags(cl, obj, NULL,
127 MUIA_Group_Horiz, TRUE,
128 MUIA_InnerLeft, 0,
129 MUIA_InnerRight, 0,
130 MUIA_Group_Spacing, 0,
131 TAG_MORE, msg->ops_AttrList);
133 if (!obj)
134 return (IPTR) NULL;
136 data = INST_DATA(cl, obj);
137 data->list = list;
138 data->vert = vert;
140 data->hook.h_Entry = HookEntry;
141 data->hook.h_SubEntry = (HOOKFUNC) Listview_Function;
142 data->hook.h_Data = data;
144 data->selfnotify_hook.h_Entry = HookEntry;
145 data->selfnotify_hook.h_SubEntry = (HOOKFUNC) SelfNotify_Function;
146 data->selfnotify_hook.h_Data = data;
147 data->noforward = FALSE;
149 data->last_active = -1;
151 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY;
152 data->ehn.ehn_Priority = 0;
153 data->ehn.ehn_Flags = 0;
154 data->ehn.ehn_Object = obj;
155 data->ehn.ehn_Class = cl;
157 /* parse initial taglist */
158 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
160 switch (tag->ti_Tag)
162 case MUIA_Listview_DoubleClick:
163 data->doubleclick = tag->ti_Data != 0;
164 break;
165 case MUIA_Listview_Input:
166 data->read_only = !tag->ti_Data;
167 break;
168 case MUIA_Listview_MultiSelect:
169 data->multiselect = tag->ti_Data;
170 break;
171 case MUIA_Listview_ScrollerPos:
172 data->scroller_pos = tag->ti_Data;
173 break;
177 /* Add list and/or scroller */
178 switch (data->scroller_pos)
180 case MUIV_Listview_ScrollerPos_None:
181 DoMethod(obj, OM_ADDMEMBER, list);
182 break;
183 case MUIV_Listview_ScrollerPos_Left:
184 DoMethod(obj, OM_ADDMEMBER, vert);
185 DoMethod(obj, OM_ADDMEMBER, list);
186 break;
187 default:
188 DoMethod(obj, OM_ADDMEMBER, list);
189 DoMethod(obj, OM_ADDMEMBER, vert);
190 break;
193 get(list, MUIA_List_VertProp_First, &first);
194 get(list, MUIA_List_VertProp_Visible, &visible);
195 get(list, MUIA_List_VertProp_Entries, &entries);
197 D(bug
198 ("[ListView 0x%p] List 0x%p, First %ld, Visible %ld, Entries %ld\n",
199 obj, list, first, visible, entries));
201 SetAttrs(data->vert,
202 MUIA_Prop_First, first,
203 MUIA_Prop_Visible, visible, MUIA_Prop_Entries, entries, TAG_DONE);
205 DoMethod(vert, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, (IPTR) obj,
206 4, MUIM_CallHook, (IPTR) &data->hook, PROP_VERT_FIRST,
207 MUIV_TriggerValue);
208 DoMethod(list, MUIM_Notify, MUIA_List_VertProp_First, MUIV_EveryTime,
209 (IPTR) obj, 4, MUIM_CallHook, (IPTR) &data->hook, LIST_VERT_FIRST,
210 MUIV_TriggerValue);
211 DoMethod(list, MUIM_Notify, MUIA_List_VertProp_Visible, MUIV_EveryTime,
212 (IPTR) obj, 4, MUIM_CallHook, (IPTR) &data->hook,
213 LIST_VERT_VISIBLE, MUIV_TriggerValue);
214 DoMethod(list, MUIM_Notify, MUIA_List_VertProp_Entries, MUIV_EveryTime,
215 (IPTR) obj, 4, MUIM_CallHook, (IPTR) &data->hook,
216 LIST_VERT_ENTRIES, MUIV_TriggerValue);
217 DoMethod(list, MUIM_Notify, MUIA_List_Active, MUIV_EveryTime,
218 (IPTR) obj, 4, MUIM_CallHook, (IPTR) &data->selfnotify_hook,
219 MUIA_List_Active, MUIV_TriggerValue);
221 return (IPTR) obj;
224 /**************************************************************************
225 OM_DISPOSE
226 **************************************************************************/
227 IPTR Listview__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
229 return DoSuperMethodA(cl, obj, msg);
232 /**************************************************************************
233 OM_SET
234 **************************************************************************/
235 IPTR Listview__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
237 struct TagItem *tag, *tags;
238 IPTR no_notify = GetTagData(MUIA_NoNotify, FALSE, msg->ops_AttrList);
239 struct MUI_ListviewData *data = INST_DATA(cl, obj);
241 if (data->noforward)
243 return DoSuperMethodA(cl, obj, (Msg) msg);
246 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
248 switch (tag->ti_Tag)
250 case MUIA_List_CompareHook:
251 case MUIA_List_ConstructHook:
252 case MUIA_List_DestructHook:
253 case MUIA_List_DisplayHook:
254 case MUIA_List_VertProp_First:
255 case MUIA_List_Format:
256 case MUIA_List_VertProp_Entries:
257 case MUIA_List_VertProp_Visible:
258 case MUIA_List_Active:
259 case MUIA_List_First:
260 case MUIA_List_Visible:
261 case MUIA_List_Entries:
262 case MUIA_List_Quiet:
263 SetAttrs(data->list, MUIA_NoNotify, no_notify, tag->ti_Tag,
264 tag->ti_Data, TAG_DONE);
265 break;
266 case MUIA_Listview_DoubleClick:
267 data->doubleclick = tag->ti_Data != 0;
268 break;
269 case MUIA_Listview_SelectChange:
270 data->select_change = tag->ti_Data != 0;
271 break;
272 case MUIA_Disabled:
273 if (_flags(obj) & MADF_SETUP)
275 /* Stop listening for events we only listen to when mouse
276 button is down: we will not be informed of the button
277 being released */
278 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
279 (IPTR) &data->ehn);
280 data->ehn.ehn_Events &= ~(IDCMP_MOUSEMOVE | IDCMP_INTUITICKS
281 | IDCMP_INACTIVEWINDOW);
282 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
283 (IPTR) &data->ehn);
285 break;
289 return DoSuperMethodA(cl, obj, (Msg) msg);
292 /**************************************************************************
293 OM_GET
294 **************************************************************************/
295 IPTR Listview__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
297 /* small macro to simplify return value storage */
298 #define STORE *(msg->opg_Storage)
299 struct MUI_ListviewData *data = INST_DATA(cl, obj);
301 switch (msg->opg_AttrID)
303 case MUIA_List_CompareHook:
304 case MUIA_List_ConstructHook:
305 case MUIA_List_DestructHook:
306 case MUIA_List_DisplayHook:
307 case MUIA_List_VertProp_First:
308 case MUIA_List_Format:
309 case MUIA_List_VertProp_Entries:
310 case MUIA_List_VertProp_Visible:
311 case MUIA_List_Active:
312 case MUIA_List_First:
313 case MUIA_List_Visible:
314 case MUIA_List_Entries:
315 case MUIA_List_Quiet:
316 return GetAttr(msg->opg_AttrID, data->list, msg->opg_Storage);
317 case MUIA_Listview_DoubleClick:
318 STORE = data->doubleclick;
319 return 1;
320 case MUIA_Listview_ClickColumn:
321 STORE = data->click_column;
322 return 1;
323 case MUIA_Listview_List:
324 STORE = (IPTR) data->list;
325 return 1;
326 case MUIA_Listview_SelectChange:
327 STORE = data->select_change;
328 return 1;
331 return DoSuperMethodA(cl, obj, (Msg) msg);
332 #undef STORE
335 /**************************************************************************
336 MUIM_Setup
337 **************************************************************************/
338 IPTR Listview__MUIM_Setup(struct IClass *cl, Object *obj,
339 struct MUIP_Setup *msg)
341 struct MUI_ListviewData *data = INST_DATA(cl, obj);
343 if (!DoSuperMethodA(cl, obj, (Msg) msg))
344 return 0;
346 data->prefs_multi = muiGlobalInfo(obj)->mgi_Prefs->list_multi;
347 if (data->multiselect == MUIV_Listview_MultiSelect_Default)
349 if (data->prefs_multi == LISTVIEW_MULTI_SHIFTED)
350 data->multiselect = MUIV_Listview_MultiSelect_Shifted;
351 else
352 data->multiselect = MUIV_Listview_MultiSelect_Always;
355 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR) &data->ehn);
357 return 1;
360 /**************************************************************************
361 MUIM_Cleanup
362 **************************************************************************/
363 IPTR Listview__MUIM_Cleanup(struct IClass *cl, Object *obj,
364 struct MUIP_Cleanup *msg)
366 struct MUI_ListviewData *data = INST_DATA(cl, obj);
368 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR) &data->ehn);
369 data->mouse_click = 0;
371 return DoSuperMethodA(cl, obj, (Msg) msg);
374 /**************************************************************************
375 MUIM_HandleEvent
376 **************************************************************************/
377 IPTR Listview__MUIM_HandleEvent(struct IClass *cl, Object *obj,
378 struct MUIP_HandleEvent *msg)
380 struct MUI_ListviewData *data = INST_DATA(cl, obj);
381 Object *list = data->list;
382 struct MUI_List_TestPos_Result pos;
383 LONG seltype, old_active, new_active, visible, first, last, i;
384 IPTR result = 0;
385 BOOL select = FALSE, clear = FALSE, range_select = FALSE, changing;
386 WORD delta;
387 typeof(msg->muikey) muikey = msg->muikey;
389 new_active = old_active = XGET(list, MUIA_List_Active);
390 visible = XGET(list, MUIA_List_Visible);
392 if (muikey != MUIKEY_NONE)
394 result = MUI_EventHandlerRC_Eat;
396 /* Make keys behave differently in read-only mode */
397 if (data->read_only)
399 switch (muikey)
401 case MUIKEY_TOP:
402 muikey = MUIKEY_LINESTART;
403 break;
405 case MUIKEY_BOTTOM:
406 muikey = MUIKEY_LINEEND;
407 break;
409 case MUIKEY_UP:
410 muikey = MUIKEY_LEFT;
411 break;
413 case MUIKEY_DOWN:
414 case MUIKEY_PRESS:
415 muikey = MUIKEY_RIGHT;
416 break;
420 switch (muikey)
422 case MUIKEY_TOGGLE:
423 if (data->multiselect != MUIV_Listview_MultiSelect_None
424 && !data->read_only)
426 select = TRUE;
427 data->click_column = data->def_click_column;
428 new_active = MUIV_List_Active_Down;
430 else
432 DoMethod(list, MUIM_List_Jump, 0);
433 muikey = MUIKEY_NONE;
435 break;
437 case MUIKEY_TOP:
438 new_active = MUIV_List_Active_Top;
439 break;
441 case MUIKEY_BOTTOM:
442 new_active = MUIV_List_Active_Bottom;
443 break;
445 case MUIKEY_LEFT:
446 case MUIKEY_WORDLEFT:
447 DoMethod(list, MUIM_List_Jump, MUIV_List_Jump_Up);
448 break;
450 case MUIKEY_RIGHT:
451 case MUIKEY_WORDRIGHT:
452 DoMethod(list, MUIM_List_Jump, MUIV_List_Jump_Down);
453 break;
455 case MUIKEY_LINESTART:
456 DoMethod(list, MUIM_List_Jump, MUIV_List_Jump_Top);
457 break;
459 case MUIKEY_LINEEND:
460 DoMethod(list, MUIM_List_Jump, MUIV_List_Jump_Bottom);
461 break;
463 case MUIKEY_UP:
464 new_active = MUIV_List_Active_Up;
465 break;
467 case MUIKEY_DOWN:
468 new_active = MUIV_List_Active_Down;
469 break;
471 case MUIKEY_PAGEUP:
472 if (data->read_only)
473 DoWheelMove(cl, obj, -visible);
474 else
475 new_active = MUIV_List_Active_PageUp;
476 break;
478 case MUIKEY_PAGEDOWN:
479 if (data->read_only)
480 DoWheelMove(cl, obj, visible);
481 else
482 new_active = MUIV_List_Active_PageDown;
483 break;
485 default:
486 result = 0;
489 else if (msg->imsg)
491 DoMethod(list, MUIM_List_TestPos, msg->imsg->MouseX,
492 msg->imsg->MouseY, (IPTR) &pos);
494 switch (msg->imsg->Class)
496 case IDCMP_MOUSEBUTTONS:
497 if (msg->imsg->Code == SELECTDOWN)
499 if (_isinobject(list, msg->imsg->MouseX, msg->imsg->MouseY))
501 data->mouse_click = MOUSE_CLICK_ENTRY;
503 if (!data->read_only && pos.entry != -1)
505 new_active = pos.entry;
507 clear = (data->multiselect
508 == MUIV_Listview_MultiSelect_Shifted
509 && (msg->imsg->Qualifier
510 & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) == 0);
511 seltype = clear ?
512 MUIV_List_Select_On: MUIV_List_Select_Toggle;
513 select = data->multiselect
514 != MUIV_Listview_MultiSelect_None;
516 /* Handle MUIA_Listview_ClickColumn */
517 data->click_column = pos.column;
518 superset(cl, obj, MUIA_Listview_ClickColumn,
519 data->click_column);
521 /* Handle double clicking */
522 if (data->last_active == pos.entry
523 && DoubleClick(data->last_secs, data->last_mics,
524 msg->imsg->Seconds, msg->imsg->Micros))
526 set(obj, MUIA_Listview_DoubleClick, TRUE);
527 data->last_active = -1;
528 data->last_secs = data->last_mics = 0;
530 else
532 data->last_active = pos.entry;
533 data->last_secs = msg->imsg->Seconds;
534 data->last_mics = msg->imsg->Micros;
537 /* Look out for mouse movement, timer and
538 inactive-window events while mouse button is
539 down */
540 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
541 (IPTR) &data->ehn);
542 data->ehn.ehn_Events |= (IDCMP_MOUSEMOVE
543 | IDCMP_INTUITICKS |IDCMP_INACTIVEWINDOW);
544 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
545 (IPTR) &data->ehn);
549 else
551 /* Activate object */
552 if (msg->imsg->Code == SELECTUP && data->mouse_click)
554 set(_win(obj), MUIA_Window_ActiveObject, (IPTR)obj);
555 data->mouse_click = 0;
558 /* Restore normal event mask */
559 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
560 (IPTR) &data->ehn);
561 data->ehn.ehn_Events &= ~(IDCMP_MOUSEMOVE | IDCMP_INTUITICKS
562 | IDCMP_INACTIVEWINDOW);
563 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
564 (IPTR) &data->ehn);
566 break;
568 case IDCMP_MOUSEMOVE:
569 case IDCMP_INTUITICKS:
570 if (pos.flags & MUI_LPR_ABOVE)
571 new_active = MUIV_List_Active_Up;
572 else if (pos.flags & MUI_LPR_BELOW)
573 new_active = MUIV_List_Active_Down;
574 else
575 new_active = pos.entry;
577 select = new_active != old_active
578 && data->multiselect != MUIV_Listview_MultiSelect_None;
579 if (select)
581 DoMethod(list, MUIM_List_Select, MUIV_List_Select_Active,
582 MUIV_List_Select_Ask, &seltype);
583 range_select = new_active >= 0;
586 break;
588 case IDCMP_INACTIVEWINDOW:
589 /* Stop listening for events we only listen to when mouse button is
590 down: we will not be informed of the button being released */
591 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
592 (IPTR) &data->ehn);
593 data->ehn.ehn_Events &=
594 ~(IDCMP_MOUSEMOVE | IDCMP_INTUITICKS | IDCMP_INACTIVEWINDOW);
595 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
596 (IPTR) &data->ehn);
597 break;
599 case IDCMP_RAWKEY:
600 /* Scroll wheel */
601 if (_isinobject(data->vert, msg->imsg->MouseX, msg->imsg->MouseY))
602 delta = 1;
603 else if (_isinobject(list, msg->imsg->MouseX, msg->imsg->MouseY))
604 delta = 4;
605 else
606 delta = 0;
608 if (delta != 0)
610 switch (msg->imsg->Code)
612 case RAWKEY_NM_WHEEL_UP:
613 DoWheelMove(cl, obj, -delta);
614 break;
616 case RAWKEY_NM_WHEEL_DOWN:
617 DoWheelMove(cl, obj, delta);
618 break;
620 result = MUI_EventHandlerRC_Eat;
622 break;
626 /* Decide in advance if any selections may change */
627 changing = clear || muikey == MUIKEY_TOGGLE || select;
629 /* Change selected and active entries */
630 if (changing)
631 set(obj, MUIA_Listview_SelectChange, TRUE);
633 if (clear)
635 DoMethod(list, MUIM_List_Select, MUIV_List_Select_All,
636 MUIV_List_Select_Off, NULL);
639 if (muikey == MUIKEY_TOGGLE)
641 DoMethod(list, MUIM_List_Select,
642 MUIV_List_Select_Active,
643 MUIV_List_Select_Toggle, NULL);
644 select = FALSE;
647 if (new_active != old_active)
648 set(list, MUIA_List_Active, new_active);
650 if (select)
652 if (range_select)
654 if (old_active < new_active)
655 first = old_active + 1, last = new_active;
656 else
657 first = new_active, last = old_active - 1;
658 for (i = first; i <= last; i++)
659 DoMethod(list, MUIM_List_Select, i, seltype, NULL);
661 else
662 DoMethod(list, MUIM_List_Select, MUIV_List_Select_Active, seltype,
663 NULL);
666 if (changing)
667 set(obj, MUIA_Listview_SelectChange, FALSE);
669 return result;
672 static void DoWheelMove(struct IClass *cl, Object *obj, LONG wheely)
674 struct MUI_ListviewData *data = INST_DATA(cl, obj);
675 LONG new, first, entries, visible;
677 new = first = XGET(data->list, MUIA_List_First);
678 entries = XGET(data->list, MUIA_List_Entries);
679 visible = XGET(data->list, MUIA_List_Visible);
681 new += wheely;
683 if (new > entries - visible)
685 new = entries - visible;
688 if (new < 0)
690 new = 0;
693 if (new != first)
695 set(data->list, MUIA_List_First, new);
699 BOOPSI_DISPATCHER(IPTR, Listview_Dispatcher, cl, obj, msg)
701 switch (msg->MethodID)
703 case OM_SET:
704 return Listview__OM_SET(cl, obj, (struct opSet *)msg);
705 case OM_GET:
706 return Listview__OM_GET(cl, obj, (struct opGet *)msg);
707 case OM_NEW:
708 return Listview__OM_NEW(cl, obj, (struct opSet *)msg);
709 case OM_DISPOSE:
710 return Listview__OM_DISPOSE(cl, obj, msg);
711 case MUIM_Setup:
712 return Listview__MUIM_Setup(cl, obj, (struct MUIP_Setup *)msg);
713 case MUIM_Cleanup:
714 return Listview__MUIM_Cleanup(cl, obj, (struct MUIP_Cleanup *)msg);
715 case MUIM_HandleEvent:
716 return Listview__MUIM_HandleEvent(cl, obj,
717 (struct MUIP_HandleEvent *)msg);
718 case MUIM_List_Clear:
719 case MUIM_List_CreateImage:
720 case MUIM_List_DeleteImage:
721 case MUIM_List_Exchange:
722 case MUIM_List_GetEntry:
723 case MUIM_List_Insert:
724 case MUIM_List_InsertSingle:
725 case MUIM_List_Jump:
726 case MUIM_List_NextSelected:
727 case MUIM_List_Redraw:
728 case MUIM_List_Remove:
729 case MUIM_List_Select:
730 case MUIM_List_Sort:
731 case MUIM_List_TestPos:
733 struct MUI_ListviewData *data = INST_DATA(cl, obj);
735 return DoMethodA(data->list, msg);
740 return DoSuperMethodA(cl, obj, msg);
742 BOOPSI_DISPATCHER_END
745 * Class descriptor.
747 const struct __MUIBuiltinClass _MUI_Listview_desc =
749 MUIC_Listview,
750 MUIC_Group,
751 sizeof(struct MUI_ListviewData),
752 (void *) Listview_Dispatcher