2 Copyright © 2002-2015, The AROS Development Team. All rights reserved.
9 #include <exec/memory.h>
10 #include <graphics/gfx.h>
11 #include <graphics/gfxmacros.h>
12 #include <graphics/view.h>
13 #include <devices/rawkeycodes.h>
14 #include <clib/alib_protos.h>
15 #include <proto/exec.h>
16 #include <proto/graphics.h>
17 #include <proto/utility.h>
18 #include <proto/dos.h>
19 #include <proto/intuition.h>
20 #include <proto/muimaster.h>
22 /* #define MYDEBUG 1 */
25 #include "muimaster_intern.h"
28 #include "textengine.h"
29 #include "listimage.h"
32 extern struct Library
*MUIMasterBase
;
34 #define ENTRY_TITLE (-1)
36 #define FORMAT_TEMPLATE "DELTA=D/N,PREPARSE=P/K,WEIGHT=W/N,MINWIDTH=MIW/N," \
37 "MAXWIDTH=MAW/N,COL=C/N,BAR/S"
57 LONG
*widths
; /* Widths of the columns */
58 LONG width
; /* Line width */
59 LONG height
; /* Line height */
60 WORD flags
; /* see below */
63 #define ENTRY_SELECTED (1<<0)
68 int colno
; /* Column number */
69 int user_width
; /* user set width; -1 if entry width */
70 int min_width
; /* min width percentage */
71 int max_width
; /* min width percentage */
73 int delta
; /* ignored for the first and last column, defaults to 4 */
76 int entries_width
; /* width of the entries (maximum of all widths) */
79 struct MUI_ImageSpec_intern
;
86 APTR intern_pool
; /* The internal pool which the class has allocated */
87 LONG intern_puddle_size
;
88 LONG intern_thresh_size
;
89 APTR pool
; /* the pool which is used to allocate list entries */
91 struct Hook
*construct_hook
;
92 struct Hook
*compare_hook
;
93 struct Hook
*destruct_hook
;
94 struct Hook
*display_hook
;
95 struct Hook
*multi_test_hook
;
97 struct Hook default_compare_hook
;
99 /* List management, currently we use a simple flat array, which is not
100 * good if many entries are inserted/deleted */
101 LONG entries_num
; /* Number of Entries in the list */
102 LONG entries_allocated
;
103 struct ListEntry
**entries
;
105 LONG entries_first
; /* first visible entry */
106 LONG entries_visible
; /* number of visible entries,
107 * determined at MUIM_Layout */
109 LONG insert_position
; /* pos of the last insertion */
111 LONG entry_maxheight
; /* Maximum height of an entry */
112 ULONG entry_minheight
; /* from MUIA_List_MinLineHeight */
114 LONG entries_totalheight
;
115 LONG entries_maxwidth
;
117 LONG vertprop_entries
;
118 LONG vertprop_visible
;
121 LONG confirm_entries_num
; /* These are the correct entries num, used
122 * so you cannot set MUIA_List_Entries to
125 LONG entries_top_pixel
; /* Where the entries start */
127 /* Column managment, is allocated by ParseListFormat() and freed
128 * by CleanListFormat() */
130 LONG columns
; /* Number of columns the list has */
131 struct ColumnInfo
*ci
;
133 STRPTR
*strings
; /* the strings for the display function, one
134 * more than needed (for the entry position) */
137 int title_height
; /* The complete height of the title */
138 STRPTR title
; /* On single column lists this is the title,
139 * otherwise 1. NULL for no title(s) */
142 struct MUI_ImageSpec_intern
*list_cursor
;
143 struct MUI_ImageSpec_intern
*list_select
;
144 struct MUI_ImageSpec_intern
*list_selcur
;
146 /* Render optimization */
147 int update
; /* 1 - update everything, 2 - redraw entry at update_pos,
148 * 3 - scroll to current entries_first (old value is in
155 struct MinList images
;
158 ListviewRefresh prefs_refresh
;
159 UWORD prefs_linespacing
;
161 UWORD prefs_smoothval
;
163 /* render space handling */
167 /***************************/
168 /* Former Listview members */
169 /***************************/
178 LONG def_click_column
;
180 LONG mouse_click
; /* see below if mouse is held down */
187 struct MUI_EventHandlerNode ehn
;
190 ListviewMulti prefs_multi
;
198 #define MOUSE_CLICK_ENTRY 1 /* on entry clicked */
199 #define MOUSE_CLICK_TITLE 2 /* on title clicked */
201 #define LIST_ADJUSTWIDTH (1<<0)
202 #define LIST_ADJUSTHEIGHT (1<<1)
203 #define LIST_AUTOVISIBLE (1<<2)
204 #define LIST_DRAGSORTABLE (1<<3)
205 #define LIST_SHOWDROPMARKS (1<<4)
206 #define LIST_QUIET (1<<5)
209 /****** List.mui/MUIA_List_CompareHook ***************************************
212 * MUIA_List_CompareHook -- (V4) [IS.], struct Hook *
215 * The provided hook indicates the sort ordering of two list entries.
216 * The hook receives list-entry data pointers as its second and third
217 * arguments. The hook should return a negative value if the first entry
218 * should be placed before the second entry, a positive value if the
219 * first entry should be placed after the second entry, and zero if the
222 * In addition to being used internally for sorting operations, this hook
223 * will be called when MUIM_List_Compare is externally invoked.
225 * If this attribute is not specified or is set to NULL, all list entries
228 ******************************************************************************
232 /****** List.mui/MUIA_List_MultiTestHook *************************************
235 * MUIA_List_MultiTestHook -- (V4) [IS.], struct Hook *
238 * The provided hook indicates whether a particular list entry
239 * may be multiselected. The hook receives the list-entry data pointer as
240 * its third argument, and returns a Boolean value. If this attribute is
241 * not specified or is set to NULL, all list entries are considered
244 * Whenever an entry is about to be selected, this hook is called if
245 * there are other entries already selected. If the hook returns TRUE,
246 * the entry may be multi-selected; if the hook returns FALSE, the entry
247 * remains unselected.
249 * Additionally, if a non-multi-selectable entry has been selected (as
250 * the only selected entry in the list), any attempt to select an
251 * additional entry will fail.
253 ******************************************************************************
257 /**************************************************************************
258 Allocate a single list entry, does not initialize it (except the pointer)
259 **************************************************************************/
260 static struct ListEntry
*AllocListEntry(struct MUI_ListData
*data
)
263 struct ListEntry
*le
;
264 int size
= sizeof(struct ListEntry
) + sizeof(LONG
) * data
->columns
+ 4;
268 mem
= AllocPooled(data
->pool
, size
);
271 D(bug("List AllocListEntry %p, %ld bytes\n", mem
, size
));
273 mem
[0] = size
; /* Save the size */
274 le
= (struct ListEntry
*)(mem
+ 1);
275 le
->widths
= (LONG
*) (le
+ 1);
277 /* Initialize fields */
281 for (j
= 0; j
< data
->columns
; j
++)
287 /**************************************************************************
288 Deallocate a single list entry, does not deinitialize it
289 **************************************************************************/
290 static void FreeListEntry(struct MUI_ListData
*data
,
291 struct ListEntry
*entry
)
293 ULONG
*mem
= ((ULONG
*) entry
) - 1;
294 D(bug("FreeListEntry %p size=%ld\n", mem
, mem
[0]));
295 FreePooled(data
->pool
, mem
, mem
[0]);
298 /**************************************************************************
299 Ensures that there can be at least the given amount of entries within
300 the list. Returns 0 if not. It also allocates the space for the title.
301 It can be accessed with data->entries[ENTRY_TITLE]
302 **************************************************************************/
303 static int SetListSize(struct MUI_ListData
*data
, LONG size
)
305 struct ListEntry
**new_entries
;
306 int new_entries_allocated
;
308 if (size
+ 1 <= data
->entries_allocated
)
311 new_entries_allocated
= data
->entries_allocated
* 2 + 4;
312 if (new_entries_allocated
< size
+ 1)
313 new_entries_allocated
= size
+ 1 + 10; /* 10 is just random */
315 D(bug("List %p : SetListSize allocating %ld bytes\n", data
,
316 new_entries_allocated
* sizeof(struct ListEntry
*)));
318 AllocVec(new_entries_allocated
* sizeof(struct ListEntry
*), 0);
319 if (NULL
== new_entries
)
323 CopyMem(data
->entries
- 1, new_entries
,
324 (data
->entries_num
+ 1) * sizeof(struct ListEntry
*));
325 FreeVec(data
->entries
- 1);
327 data
->entries
= new_entries
+ 1;
328 data
->entries_allocated
= new_entries_allocated
;
332 /**************************************************************************
333 Prepares the insertion of count entries at pos.
334 This function doesn't care if there is enough space in the datastructure.
335 SetListSize() must be used first.
336 With current implementation, this call will never fail
337 **************************************************************************/
338 static int PrepareInsertListEntries(struct MUI_ListData
*data
, int pos
,
341 memmove(&data
->entries
[pos
+ count
], &data
->entries
[pos
],
342 (data
->entries_num
- pos
) * sizeof(struct ListEntry
*));
346 /**************************************************************************
347 Removes count (already deinitalized) list entries starting az pos.
348 **************************************************************************/
349 static void RemoveListEntries(struct MUI_ListData
*data
, int pos
, int count
)
351 // FIXME: segfault if entries_num = pos = count = 1
352 memmove(&data
->entries
[pos
], &data
->entries
[pos
+ count
],
353 (data
->entries_num
- (pos
+ count
)) * sizeof(struct ListEntry
*));
356 /**************************************************************************
357 Frees all memory allocated by ParseListFormat()
358 **************************************************************************/
359 static void FreeListFormat(struct MUI_ListData
*data
)
365 for (i
= 0; i
< data
->columns
; i
++)
367 FreeVec(data
->ci
[i
].preparse
);
368 data
->ci
[i
].preparse
= NULL
;
373 FreeVec(data
->preparses
);
374 data
->preparses
= NULL
;
377 FreeVec(data
->strings
- 1);
378 data
->strings
= NULL
;
383 /**************************************************************************
384 Parses the given format string (also frees a previously parsed format).
386 **************************************************************************/
387 static int ParseListFormat(struct MUI_ListData
*data
, STRPTR format
)
395 struct RDArgs
*rdargs
;
398 format
= (STRPTR
) "";
402 FreeListFormat(data
);
406 /* Count the number of columns first */
411 if (!(data
->preparses
=
412 AllocVec((new_columns
+ 10) * sizeof(STRPTR
), 0)))
415 if (!(data
->strings
= AllocVec((new_columns
+ 1 + 10)
416 * sizeof(STRPTR
), 0))) /* hold enough space also for the entry pos,
417 * used by orginal MUI and also some
421 if (!(data
->ci
= AllocVec(new_columns
* sizeof(struct ColumnInfo
), 0)))
425 for (i
= 0; i
< new_columns
; i
++)
427 data
->ci
[i
].colno
= -1; // -1 means: use unassigned column
428 data
->ci
[i
].weight
= 100;
429 data
->ci
[i
].delta
= 4;
430 data
->ci
[i
].min_width
= -1;
431 data
->ci
[i
].max_width
= -1;
432 data
->ci
[i
].user_width
= -1;
433 data
->ci
[i
].bar
= FALSE
;
434 data
->ci
[i
].preparse
= NULL
;
437 if ((format_sep
= StrDup(format
)) != 0)
439 for (i
= 0; format_sep
[i
] != '\0'; i
++)
441 if (format_sep
[i
] == ',')
442 format_sep
[i
] = '\0';
445 if ((rdargs
= AllocDosObject(DOS_RDARGS
, NULL
)) != 0)
451 rdargs
->RDA_Source
.CS_Buffer
= ptr
;
452 rdargs
->RDA_Source
.CS_Length
= strlen(ptr
);
453 rdargs
->RDA_Source
.CS_CurChr
= 0;
454 rdargs
->RDA_DAList
= 0;
455 rdargs
->RDA_Buffer
= NULL
;
456 rdargs
->RDA_BufSiz
= 0;
457 rdargs
->RDA_ExtHelp
= NULL
;
458 rdargs
->RDA_Flags
= 0;
460 memset(args
, 0, sizeof args
);
461 if (ReadArgs(FORMAT_TEMPLATE
, args
, rdargs
))
464 data
->ci
[i
].colno
= *(LONG
*) args
[ARG_COL
];
465 if (args
[ARG_WEIGHT
])
466 data
->ci
[i
].weight
= *(LONG
*) args
[ARG_WEIGHT
];
468 data
->ci
[i
].delta
= *(LONG
*) args
[ARG_DELTA
];
469 if (args
[ARG_MINWIDTH
])
470 data
->ci
[i
].min_width
=
471 *(LONG
*) args
[ARG_MINWIDTH
];
472 if (args
[ARG_MAXWIDTH
])
473 data
->ci
[i
].max_width
=
474 *(LONG
*) args
[ARG_MAXWIDTH
];
475 data
->ci
[i
].bar
= args
[ARG_BAR
];
476 if (args
[ARG_PREPARSE
])
477 data
->ci
[i
].preparse
=
478 StrDup((STRPTR
) args
[ARG_PREPARSE
]);
482 ptr
+= strlen(ptr
) + 1;
485 while (i
< new_columns
);
486 FreeDosObject(DOS_RDARGS
, rdargs
);
491 for (i
= 0; i
< new_columns
; i
++)
493 D(bug("colno %d weight %d delta %d preparse %s\n",
494 data
->ci
[i
].colno
, data
->ci
[i
].weight
, data
->ci
[i
].delta
,
495 data
->ci
[i
].preparse
));
498 data
->columns
= new_columns
;
499 data
->strings
++; /* Skip entry pos */
504 /**************************************************************************
505 Call the MUIM_List_Display for the given entry. It fills out
506 data->string and data->preparses
507 **************************************************************************/
508 static void DisplayEntry(struct IClass
*cl
, Object
*obj
, int entry_pos
)
510 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
514 for (col
= 0; col
< data
->columns
; col
++)
515 data
->preparses
[col
] = data
->ci
[col
].preparse
;
517 if (entry_pos
== ENTRY_TITLE
)
519 if ((data
->columns
== 1) && (data
->title
!= (STRPTR
) 1))
521 *data
->strings
= data
->title
;
524 entry_data
= NULL
; /* it's a title request */
527 entry_data
= data
->entries
[entry_pos
]->data
;
529 /* Get the display formation */
530 DoMethod(obj
, MUIM_List_Display
, (IPTR
) entry_data
,
531 (IPTR
) data
->strings
, entry_pos
, (IPTR
) data
->preparses
);
534 /**************************************************************************
535 Determine the dims of a single entry and adapt the columninfo according
536 to it. pos might be ENTRY_TITLE. Returns 0 if pos entry needs to
537 be redrawn after this operation, 1 if all entries need to be redrawn.
538 **************************************************************************/
539 static int CalcDimsOfEntry(struct IClass
*cl
, Object
*obj
, int pos
)
541 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
542 struct ListEntry
*entry
= data
->entries
[pos
];
549 if (!(_flags(obj
) & MADF_SETUP
))
552 DisplayEntry(cl
, obj
, pos
);
554 /* Set height to at least minheight */
555 if (data
->entries
[pos
]->height
< data
->entry_minheight
)
556 data
->entries
[pos
]->height
= data
->entry_minheight
;
558 for (j
= 0; j
< data
->columns
; j
++)
561 zune_text_new(data
->preparses
[j
], data
->strings
[j
],
565 zune_text_get_bounds(text
, obj
);
567 if (text
->height
> data
->entries
[pos
]->height
)
569 data
->entries
[pos
]->height
= text
->height
;
570 /* entry height changed, redraw all entries later */
573 data
->entries
[pos
]->widths
[j
] = text
->width
;
575 if (text
->width
> data
->ci
[j
].entries_width
)
577 /* This columns width is bigger than the other in the same
578 * columns, so we store this value
580 data
->ci
[j
].entries_width
= text
->width
;
581 /* column width changed, redraw all entries later */
585 zune_text_destroy(text
);
588 if (data
->entries
[pos
]->height
> data
->entry_maxheight
)
590 data
->entry_maxheight
= data
->entries
[pos
]->height
;
591 /* maximum entry height changed, redraw all entries later */
598 /**************************************************************************
599 Determine the widths of the entries
600 **************************************************************************/
601 static void CalcWidths(struct IClass
*cl
, Object
*obj
)
604 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
606 if (!(_flags(obj
) & MADF_SETUP
))
609 for (j
= 0; j
< data
->columns
; j
++)
610 data
->ci
[j
].entries_width
= 0;
612 data
->entry_maxheight
= 0;
613 data
->entries_totalheight
= 0;
614 data
->entries_maxwidth
= 0;
616 for (i
= (data
->title
? ENTRY_TITLE
: 0); i
< data
->entries_num
; i
++)
618 CalcDimsOfEntry(cl
, obj
, i
);
619 data
->entries_totalheight
+= data
->entries
[i
]->height
;
622 for (j
= 0; j
< data
->columns
; j
++)
623 data
->entries_maxwidth
+= data
->ci
[j
].entries_width
;
625 if (!data
->entry_maxheight
)
626 data
->entry_maxheight
= 1;
629 /**************************************************************************
630 Calculates the number of visible entry lines. Returns 1 if it has
632 **************************************************************************/
633 static int CalcVertVisible(struct IClass
*cl
, Object
*obj
)
635 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
636 int old_entries_visible
= data
->entries_visible
;
637 int old_entries_top_pixel
= data
->entries_top_pixel
;
639 data
->entries_visible
= (_mheight(data
->area
) - data
->title_height
)
640 / (data
->entry_maxheight
/* + data->prefs_linespacing */ );
642 /* Distribute extra vertical space evenly between top and bottom of
645 data
->entries_top_pixel
= _mtop(data
->area
) + data
->title_height
646 + (_mheight(data
->area
) - data
->title_height
648 data
->entries_visible
*
649 (data
->entry_maxheight
/* + data->prefs_linespacing */ )) / 2;
651 return (old_entries_visible
!= data
->entries_visible
)
652 || (old_entries_top_pixel
!= data
->entries_top_pixel
);
655 /**************************************************************************
656 Default hook to compare two list entries. Works for strings only.
657 **************************************************************************/
658 AROS_UFH3S(int, default_compare_func
,
659 AROS_UFHA(struct Hook
*, h
, A0
),
660 AROS_UFHA(char *, s2
, A2
),
661 AROS_UFHA(char *, s1
, A1
))
665 return Stricmp(s1
, s2
);
670 /**************************************************************************
672 **************************************************************************/
673 IPTR
List__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
675 struct MUI_ListData
*data
;
677 struct TagItem
*tags
;
679 LONG new_entries_active
= MUIV_List_Active_Off
;
680 struct TagItem rectattrs
[2] = {{TAG_IGNORE
, TAG_IGNORE
}, {TAG_DONE
, TAG_DONE
}};
683 /* search for MUIA_Frame as it has to be passed to rectangle object */
684 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
686 if (tag
->ti_Tag
== MUIA_Frame
)
688 rectattrs
[0].ti_Tag
= MUIA_Frame
;
689 rectattrs
[0].ti_Data
= tag
->ti_Data
;
690 tag
->ti_Tag
= TAG_IGNORE
;
695 obj
= (Object
*) DoSuperNewTags(cl
, obj
, NULL
,
696 MUIA_Group_Horiz
, TRUE
,
699 MUIA_Group_Spacing
, 0,
700 MUIA_Font
, MUIV_Font_List
,
701 MUIA_ShowSelState
, FALSE
,
702 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
703 MUIA_Background
, MUII_ListBack
,
704 TAG_MORE
, (IPTR
) msg
->ops_AttrList
,
710 data
= INST_DATA(cl
, obj
);
713 data
->entries_active
= MUIV_List_Active_Off
;
714 data
->intern_puddle_size
= 2008;
715 data
->intern_thresh_size
= 1024;
716 data
->default_compare_hook
.h_Entry
= (HOOKFUNC
) default_compare_func
;
717 data
->default_compare_hook
.h_SubEntry
= 0;
718 data
->compare_hook
= &(data
->default_compare_hook
);
719 data
->flags
= LIST_SHOWDROPMARKS
;
720 data
->area_replaced
= FALSE
;
722 data
->last_active
= -1;
724 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
| IDCMP_RAWKEY
;
725 data
->ehn
.ehn_Priority
= 0;
726 data
->ehn
.ehn_Flags
= 0;
727 data
->ehn
.ehn_Object
= obj
;
728 data
->ehn
.ehn_Class
= cl
;
730 area
= (Object
*)GetTagData(MUIA_List_ListArea
, (IPTR
) 0, msg
->ops_AttrList
);
733 area
= RectangleObject
, TAG_MORE
, (IPTR
) rectattrs
, End
;
735 data
->area_replaced
= TRUE
;
738 vert
= ScrollbarObject
, MUIA_Group_Horiz
, FALSE
, End
;
741 /* parse initial taglist */
742 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
746 case MUIA_List_Active
:
747 new_entries_active
= tag
->ti_Data
;
751 data
->pool
= (APTR
) tag
->ti_Data
;
754 case MUIA_List_PoolPuddleSize
:
755 data
->intern_puddle_size
= tag
->ti_Data
;
758 case MUIA_List_PoolThreshSize
:
759 data
->intern_thresh_size
= tag
->ti_Data
;
762 case MUIA_List_CompareHook
:
763 data
->compare_hook
= (struct Hook
*)tag
->ti_Data
;
764 if (data
->compare_hook
== NULL
)
765 data
->compare_hook
= &data
->default_compare_hook
;
768 case MUIA_List_ConstructHook
:
769 data
->construct_hook
= (struct Hook
*)tag
->ti_Data
;
772 case MUIA_List_DestructHook
:
773 data
->destruct_hook
= (struct Hook
*)tag
->ti_Data
;
776 case MUIA_List_DisplayHook
:
777 data
->display_hook
= (struct Hook
*)tag
->ti_Data
;
780 case MUIA_List_MultiTestHook
:
781 data
->multi_test_hook
= (struct Hook
*)tag
->ti_Data
;
784 case MUIA_List_SourceArray
:
785 array
= (APTR
*) tag
->ti_Data
;
788 case MUIA_List_Format
:
789 data
->format
= StrDup((STRPTR
) tag
->ti_Data
);
792 case MUIA_List_Title
:
793 data
->title
= (STRPTR
) tag
->ti_Data
;
796 case MUIA_List_MinLineHeight
:
797 data
->entry_minheight
= tag
->ti_Data
;
800 case MUIA_List_AdjustHeight
:
801 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_ADJUSTHEIGHT
);
804 case MUIA_List_AdjustWidth
:
805 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_ADJUSTWIDTH
);
808 case MUIA_List_AutoVisible
:
809 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_AUTOVISIBLE
);
812 case MUIA_List_ShowDropMarks
:
813 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_SHOWDROPMARKS
);
816 case MUIA_List_DragSortable
:
817 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_DRAGSORTABLE
);
818 set(obj
, MUIA_Draggable
, tag
->ti_Data
);
821 case MUIA_Listview_ScrollerPos
:
822 data
->scroller_pos
= tag
->ti_Data
;
825 case MUIA_Listview_Input
:
826 data
->read_only
= !tag
->ti_Data
;
829 case MUIA_Listview_MultiSelect
:
830 data
->multiselect
= tag
->ti_Data
;
833 case MUIA_Listview_DoubleClick
:
834 data
->doubleclick
= tag
->ti_Data
!= 0;
839 /* Add list and/or scroller */
840 switch (data
->scroller_pos
)
842 case MUIV_Listview_ScrollerPos_None
:
843 DoMethod(obj
, OM_ADDMEMBER
, area
);
845 case MUIV_Listview_ScrollerPos_Left
:
846 DoMethod(obj
, OM_ADDMEMBER
, vert
);
847 DoMethod(obj
, OM_ADDMEMBER
, area
);
850 DoMethod(obj
, OM_ADDMEMBER
, area
);
851 DoMethod(obj
, OM_ADDMEMBER
, vert
);
857 LONG entries
= 0, first
= 0, visible
= 0;
859 get(obj
, MUIA_List_VertProp_First
, &first
);
860 get(obj
, MUIA_List_VertProp_Visible
, &visible
);
861 get(obj
, MUIA_List_VertProp_Entries
, &entries
);
864 MUIA_Prop_First
, first
,
865 MUIA_Prop_Visible
, visible
, MUIA_Prop_Entries
, entries
, TAG_DONE
);
867 /* Pass prop object as DestObj (based on code in NList) */
868 DoMethod(obj
, MUIM_Notify
, MUIA_List_VertProp_First
, MUIV_EveryTime
,
869 (IPTR
) vert
, 3, MUIM_NoNotifySet
, MUIA_Prop_First
, MUIV_TriggerValue
);
870 DoMethod(obj
, MUIM_Notify
, MUIA_List_VertProp_Visible
, MUIV_EveryTime
,
871 (IPTR
) vert
, 3, MUIM_NoNotifySet
, MUIA_Prop_Visible
, MUIV_TriggerValue
);
872 DoMethod(obj
, MUIM_Notify
, MUIA_List_VertProp_Entries
, MUIV_EveryTime
,
873 (IPTR
) vert
, 3, MUIM_NoNotifySet
, MUIA_Prop_Entries
, MUIV_TriggerValue
);
878 /* No memory pool given, so we create our own */
879 data
->pool
= data
->intern_pool
=
880 CreatePool(0, data
->intern_puddle_size
,
881 data
->intern_thresh_size
);
884 CoerceMethod(cl
, obj
, OM_DISPOSE
);
889 /* parse the list format */
890 if (!(ParseListFormat(data
, data
->format
)))
892 CoerceMethod(cl
, obj
, OM_DISPOSE
);
896 /* This is neccessary for at least the title */
897 if (!SetListSize(data
, 0))
899 CoerceMethod(cl
, obj
, OM_DISPOSE
);
905 if (!(data
->entries
[ENTRY_TITLE
] = AllocListEntry(data
)))
907 CoerceMethod(cl
, obj
, OM_DISPOSE
);
912 data
->entries
[ENTRY_TITLE
] = NULL
;
917 /* Count the number of elements */
918 for (i
= 0; array
[i
] != NULL
; i
++)
921 DoMethod(obj
, MUIM_List_Insert
, (IPTR
) array
, i
,
922 MUIV_List_Insert_Top
);
925 if ((data
->entries_num
) && (new_entries_active
!= MUIV_List_Active_Off
))
927 switch (new_entries_active
)
929 case MUIV_List_Active_Top
:
930 new_entries_active
= 0;
933 case MUIV_List_Active_Bottom
:
934 new_entries_active
= data
->entries_num
- 1;
938 if (new_entries_active
< 0)
939 new_entries_active
= 0;
940 else if (new_entries_active
>= data
->entries_num
)
941 new_entries_active
= data
->entries_num
- 1;
943 data
->entries_active
= new_entries_active
;
944 /* Selected entry will be moved into visible area */
947 NewList((struct List
*)&data
->images
);
949 D(bug("List_New(%lx)\n", obj
));
954 /**************************************************************************
956 **************************************************************************/
957 IPTR
List__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
959 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
961 D(bug("List Dispose\n"));
963 /* Call destruct method for every entry and free the entries manually
964 * to avoid notification */
965 while (data
->confirm_entries_num
)
967 struct ListEntry
*lentry
=
968 data
->entries
[--data
->confirm_entries_num
];
969 DoMethod(obj
, MUIM_List_Destruct
, (IPTR
) lentry
->data
,
971 FreeListEntry(data
, lentry
);
974 if (data
->intern_pool
)
975 DeletePool(data
->intern_pool
);
977 FreeVec(data
->entries
- 1);
978 /* title is currently before all other elements */
980 FreeListFormat(data
);
981 FreeVec(data
->format
);
983 return DoSuperMethodA(cl
, obj
, msg
);
987 /**************************************************************************
989 **************************************************************************/
990 IPTR
List__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
992 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
994 struct TagItem
*tags
;
997 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
1001 case MUIA_List_CompareHook
:
1002 data
->compare_hook
= (struct Hook
*)tag
->ti_Data
;
1003 if (data
->compare_hook
== NULL
)
1004 data
->compare_hook
= &data
->default_compare_hook
;
1007 case MUIA_List_ConstructHook
:
1008 data
->construct_hook
= (struct Hook
*)tag
->ti_Data
;
1011 case MUIA_List_DestructHook
:
1012 data
->destruct_hook
= (struct Hook
*)tag
->ti_Data
;
1015 case MUIA_List_DisplayHook
:
1016 data
->display_hook
= (struct Hook
*)tag
->ti_Data
;
1019 case MUIA_List_MultiTestHook
:
1020 data
->multi_test_hook
= (struct Hook
*)tag
->ti_Data
;
1021 if (data
->multi_test_hook
!= NULL
)
1023 /* Clearing current selections is the easiest way to keep
1024 * selections consistent with the new hook */
1025 DoMethod(obj
, MUIM_List_Select
, MUIV_List_Select_All
,
1026 MUIV_List_Select_Off
, NULL
);
1030 case MUIA_List_Title
:
1031 data
->title
= (STRPTR
) tag
->ti_Data
;
1032 DoMethod(obj
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
1035 case MUIA_List_VertProp_First
:
1036 data
->vertprop_first
= tag
->ti_Data
;
1037 if (data
->entries_first
!= tag
->ti_Data
)
1039 set(obj
, MUIA_List_First
, tag
->ti_Data
);
1043 case MUIA_List_Format
:
1044 data
->format
= StrDup((STRPTR
) tag
->ti_Data
);
1045 ParseListFormat(data
, data
->format
);
1046 // FIXME: should we check for errors?
1047 DoMethod(obj
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
1050 case MUIA_List_VertProp_Entries
:
1051 data
->vertprop_entries
= tag
->ti_Data
;
1054 case MUIA_List_VertProp_Visible
:
1055 data
->vertprop_visible
= tag
->ti_Data
;
1056 data
->entries_visible
= tag
->ti_Data
;
1059 case MUIA_List_Active
:
1061 LONG new_entries_active
= tag
->ti_Data
;
1063 if ((data
->entries_num
)
1064 && (new_entries_active
!= MUIV_List_Active_Off
))
1066 switch (new_entries_active
)
1068 case MUIV_List_Active_Top
:
1069 new_entries_active
= 0;
1072 case MUIV_List_Active_Bottom
:
1073 new_entries_active
= data
->entries_num
- 1;
1076 case MUIV_List_Active_Up
:
1077 new_entries_active
= data
->entries_active
- 1;
1080 case MUIV_List_Active_Down
:
1081 new_entries_active
= data
->entries_active
+ 1;
1084 case MUIV_List_Active_PageUp
:
1085 new_entries_active
=
1086 data
->entries_active
- data
->entries_visible
;
1089 case MUIV_List_Active_PageDown
:
1090 new_entries_active
=
1091 data
->entries_active
+ data
->entries_visible
;
1095 if (new_entries_active
< 0)
1096 new_entries_active
= 0;
1097 else if (new_entries_active
>= data
->entries_num
)
1098 new_entries_active
= data
->entries_num
- 1;
1101 new_entries_active
= -1;
1103 if (data
->entries_active
!= new_entries_active
)
1105 LONG old
= data
->entries_active
;
1106 data
->entries_active
= new_entries_active
;
1108 /* Selectchange stuff */
1109 if (new_entries_active
!= -1)
1111 DoMethod(obj
, MUIM_List_SelectChange
,
1112 new_entries_active
, MUIV_List_Select_On
, 0);
1113 DoMethod(obj
, MUIM_List_SelectChange
,
1114 new_entries_active
, MUIV_List_Select_Active
, 0);
1117 DoMethod(obj
, MUIM_List_SelectChange
,
1118 MUIV_List_Active_Off
, MUIV_List_Select_Off
, 0);
1121 data
->update_pos
= old
;
1122 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1124 data
->update_pos
= data
->entries_active
;
1125 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1127 /* Make new active entry visible (if there is one and
1129 if (new_entries_active
!= -1
1130 && (_flags(obj
) & MADF_SETUP
))
1132 DoMethod(obj
, MUIM_List_Jump
,
1133 MUIV_List_Jump_Active
);
1139 case MUIA_List_First
:
1140 data
->update_pos
= data
->entries_first
;
1142 data
->entries_first
= tag
->ti_Data
;
1144 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1145 if ((data
->vertprop_first
!= tag
->ti_Data
)
1146 && (!(data
->flags
& LIST_QUIET
)))
1148 set(obj
, MUIA_List_VertProp_First
, tag
->ti_Data
);
1152 case MUIA_List_Visible
: /* Shouldn't be settable? */
1153 if (data
->vertprop_visible
!= tag
->ti_Data
)
1154 set(obj
, MUIA_List_VertProp_Visible
, tag
->ti_Data
);
1157 case MUIA_List_Entries
:
1158 if (data
->confirm_entries_num
== tag
->ti_Data
)
1160 data
->entries_num
= tag
->ti_Data
;
1161 if (!(data
->flags
& LIST_QUIET
))
1163 set(obj
, MUIA_List_VertProp_Entries
, data
->entries_num
);
1168 D(bug("Bug: confirm_entries != MUIA_List_Entries!\n"));
1172 case MUIA_List_Quiet
:
1173 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_QUIET
);
1176 DoMethod(obj
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
1177 if (data
->entries_num
!= XGET(obj
, MUIA_List_VertProp_Entries
))
1178 set(obj
, MUIA_List_VertProp_Entries
, data
->entries_num
);
1179 if (data
->vertprop_first
!=
1180 XGET(obj
, MUIA_List_VertProp_First
))
1181 set(obj
, MUIA_List_VertProp_First
, data
->vertprop_first
);
1185 case MUIA_List_AutoVisible
:
1186 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_AUTOVISIBLE
);
1189 case MUIA_List_ShowDropMarks
:
1190 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_SHOWDROPMARKS
);
1193 case MUIA_List_DragSortable
:
1194 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_DRAGSORTABLE
);
1195 set(obj
, MUIA_Draggable
, tag
->ti_Data
);
1199 /* Swallow this so the Area class doesn't redraw us */
1200 tag
->ti_Tag
= TAG_IGNORE
;
1204 if (_flags(obj
) & MADF_SETUP
)
1206 /* Stop listening for events we only listen to when mouse
1207 button is down: we will not be informed of the button
1209 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) &data
->ehn
);
1210 data
->ehn
.ehn_Events
&= ~(IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
| IDCMP_INACTIVEWINDOW
);
1211 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) &data
->ehn
);
1215 case MUIA_Listview_DoubleClick
: /* private set */
1216 data
->doubleclick
= tag
->ti_Data
!= 0;
1219 case MUIA_Listview_SelectChange
: /* private set */
1220 data
->select_change
= tag
->ti_Data
!= 0;
1225 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1228 /**************************************************************************
1230 **************************************************************************/
1231 IPTR
List__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
1233 /* small macro to simplify return value storage */
1234 #define STORE *(msg->opg_Storage)
1235 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1237 switch (msg
->opg_AttrID
)
1239 case MUIA_List_Entries
:
1240 STORE
= data
->entries_num
;
1242 case MUIA_List_First
:
1243 STORE
= data
->entries_first
;
1245 case MUIA_List_Active
:
1246 STORE
= data
->entries_active
;
1248 case MUIA_List_InsertPosition
:
1249 STORE
= data
->insert_position
;
1251 case MUIA_List_Title
:
1252 STORE
= (IPTR
) data
->title
;
1254 case MUIA_List_VertProp_Entries
:
1255 STORE
= data
->vertprop_entries
;
1257 case MUIA_List_VertProp_Visible
:
1258 case MUIA_List_Visible
:
1259 STORE
= data
->vertprop_visible
;
1261 case MUIA_List_VertProp_First
:
1262 STORE
= data
->vertprop_first
;
1264 case MUIA_List_Format
:
1265 STORE
= (IPTR
) data
->format
;
1267 case MUIA_List_AutoVisible
:
1268 STORE
= data
->flags
& LIST_AUTOVISIBLE
;
1270 case MUIA_List_ShowDropMarks
:
1271 STORE
= data
->flags
& LIST_SHOWDROPMARKS
;
1273 case MUIA_List_DragSortable
:
1274 STORE
= data
->flags
& LIST_DRAGSORTABLE
;
1276 case MUIA_Listview_ClickColumn
:
1277 STORE
= data
->click_column
;
1279 case MUIA_Listview_DoubleClick
:
1280 STORE
= data
->doubleclick
;
1282 case MUIA_Listview_SelectChange
:
1283 STORE
= data
->select_change
;
1287 if (DoSuperMethodA(cl
, obj
, (Msg
) msg
))
1293 /**************************************************************************
1295 **************************************************************************/
1296 IPTR
List__MUIM_Setup(struct IClass
*cl
, Object
*obj
,
1297 struct MUIP_Setup
*msg
)
1299 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1301 if (!DoSuperMethodA(cl
, obj
, (Msg
) msg
))
1304 data
->prefs_refresh
= muiGlobalInfo(obj
)->mgi_Prefs
->list_refresh
;
1305 data
->prefs_linespacing
=
1306 muiGlobalInfo(obj
)->mgi_Prefs
->list_linespacing
;
1307 data
->prefs_smoothed
= muiGlobalInfo(obj
)->mgi_Prefs
->list_smoothed
;
1308 data
->prefs_smoothval
= muiGlobalInfo(obj
)->mgi_Prefs
->list_smoothval
;
1310 CalcWidths(cl
, obj
);
1313 zune_imspec_setup(MUII_ListCursor
, muiRenderInfo(obj
));
1315 zune_imspec_setup(MUII_ListSelect
, muiRenderInfo(obj
));
1317 zune_imspec_setup(MUII_ListSelCur
, muiRenderInfo(obj
));
1319 data
->prefs_multi
= muiGlobalInfo(obj
)->mgi_Prefs
->list_multi
;
1320 if (data
->multiselect
== MUIV_Listview_MultiSelect_Default
)
1322 if (data
->prefs_multi
== LISTVIEW_MULTI_SHIFTED
)
1323 data
->multiselect
= MUIV_Listview_MultiSelect_Shifted
;
1325 data
->multiselect
= MUIV_Listview_MultiSelect_Always
;
1328 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) &data
->ehn
);
1333 /**************************************************************************
1335 **************************************************************************/
1336 IPTR
List__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
,
1337 struct MUIP_Cleanup
*msg
)
1339 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1340 struct ListImage
*li
= List_First(&data
->images
);
1344 struct ListImage
*next
= Node_Next(li
);
1345 DoMethod(obj
, MUIM_List_DeleteImage
, (IPTR
) li
);
1349 zune_imspec_cleanup(data
->list_cursor
);
1350 zune_imspec_cleanup(data
->list_select
);
1351 zune_imspec_cleanup(data
->list_selcur
);
1353 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) &data
->ehn
);
1354 data
->mouse_click
= 0;
1356 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1359 /**************************************************************************
1361 **************************************************************************/
1362 IPTR
List__MUIM_AskMinMax(struct IClass
*cl
, Object
*obj
,
1363 struct MUIP_AskMinMax
*msg
)
1365 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1367 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1370 if ((data
->flags
& LIST_ADJUSTWIDTH
) && (data
->entries_num
> 0))
1372 msg
->MinMaxInfo
->MinWidth
+= data
->entries_maxwidth
;
1373 msg
->MinMaxInfo
->DefWidth
+= data
->entries_maxwidth
;
1374 msg
->MinMaxInfo
->MaxWidth
+= data
->entries_maxwidth
;
1378 msg
->MinMaxInfo
->MinWidth
+= 40;
1379 msg
->MinMaxInfo
->DefWidth
+= 100;
1380 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
1383 if (data
->entries_num
> 0)
1385 if (data
->flags
& LIST_ADJUSTHEIGHT
)
1387 msg
->MinMaxInfo
->MinHeight
+= data
->entries_totalheight
;
1388 msg
->MinMaxInfo
->DefHeight
+= data
->entries_totalheight
;
1389 msg
->MinMaxInfo
->MaxHeight
+= data
->entries_totalheight
;
1393 ULONG h
= data
->entry_maxheight
+ data
->prefs_linespacing
;
1394 msg
->MinMaxInfo
->MinHeight
+= 2 * h
+ data
->prefs_linespacing
;
1395 msg
->MinMaxInfo
->DefHeight
+= 8 * h
+ data
->prefs_linespacing
;
1396 msg
->MinMaxInfo
->MaxHeight
= MUI_MAXMAX
;
1401 msg
->MinMaxInfo
->MinHeight
+= 36;
1402 msg
->MinMaxInfo
->DefHeight
+= 96;
1403 msg
->MinMaxInfo
->MaxHeight
= MUI_MAXMAX
;
1405 D(bug("List %p minheigh=%d, line maxh=%d\n",
1406 obj
, msg
->MinMaxInfo
->MinHeight
, data
->entry_maxheight
));
1410 /****i* List.mui/MUIM_Layout *************************************************
1415 ******************************************************************************
1419 IPTR
List__MUIM_Layout(struct IClass
*cl
, Object
*obj
,
1420 struct MUIP_Layout
*msg
)
1422 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1423 ULONG rc
= DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1424 LONG new_entries_first
= data
->entries_first
;
1426 /* Calc the numbers of entries visible */
1427 CalcVertVisible(cl
, obj
);
1429 /* Ensure active entry is visible if requested */
1430 if (data
->entries_active
+ 1 >=
1431 (data
->entries_first
+ data
->entries_visible
)
1432 && (data
->flags
& LIST_AUTOVISIBLE
) != 0)
1434 data
->entries_active
- data
->entries_visible
+ 1;
1436 /* Ensure there are no unnecessary empty lines */
1437 if ((new_entries_first
+ data
->entries_visible
>=
1439 && (data
->entries_visible
<= data
->entries_num
))
1440 new_entries_first
= data
->entries_num
- data
->entries_visible
;
1442 /* Always show the start of the list if it isn't long enough to fill the
1444 if (data
->entries_num
<= data
->entries_visible
)
1445 new_entries_first
= 0;
1447 if (new_entries_first
< 0)
1448 new_entries_first
= 0;
1450 set(obj
, new_entries_first
!= data
->entries_first
?
1451 MUIA_List_First
: TAG_IGNORE
, new_entries_first
);
1453 /* So the notify happens */
1454 set(obj
, MUIA_List_VertProp_Visible
, data
->entries_visible
);
1460 /**************************************************************************
1462 **************************************************************************/
1463 IPTR
List__MUIM_Show(struct IClass
*cl
, Object
*obj
,
1464 struct MUIP_Show
*msg
)
1466 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1467 ULONG rc
= DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1469 zune_imspec_show(data
->list_cursor
, obj
);
1470 zune_imspec_show(data
->list_select
, obj
);
1471 zune_imspec_show(data
->list_selcur
, obj
);
1476 /**************************************************************************
1478 **************************************************************************/
1479 IPTR
List__MUIM_Hide(struct IClass
*cl
, Object
*obj
,
1480 struct MUIP_Hide
*msg
)
1482 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1484 zune_imspec_hide(data
->list_cursor
);
1485 zune_imspec_hide(data
->list_select
);
1486 zune_imspec_hide(data
->list_selcur
);
1488 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1492 /**************************************************************************
1493 Draw an entry at entry_pos at the given row. To draw the title, set pos to
1495 **************************************************************************/
1496 static VOID
List_DrawEntry(struct IClass
*cl
, Object
*obj
, int entry_pos
,
1499 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1502 /* To be sure we don't draw anything if there is no title */
1503 if (entry_pos
== ENTRY_TITLE
&& !data
->title
)
1506 DisplayEntry(cl
, obj
, entry_pos
);
1507 x1
= _mleft(data
->area
);
1509 for (col
= 0; col
< data
->columns
; col
++)
1512 x2
= x1
+ data
->ci
[col
].entries_width
;
1515 zune_text_new(data
->preparses
[col
], data
->strings
[col
],
1516 ZTEXT_ARG_NONE
, 0)))
1518 /* Could be made simpler, as we don't really need the bounds */
1519 zune_text_get_bounds(text
, obj
);
1520 /* Note, this was MPEN_SHADOW before */
1521 SetAPen(_rp(obj
), muiRenderInfo(obj
)->mri_Pens
[MPEN_TEXT
]);
1522 zune_text_draw(text
, obj
, x1
, x2
, y
); /* totally wrong! */
1523 zune_text_destroy(text
);
1525 x1
= x2
+ data
->ci
[col
].delta
+ (data
->ci
[col
].bar
? BAR_WIDTH
: 0);
1529 /**************************************************************************
1531 **************************************************************************/
1532 IPTR
List__MUIM_Draw(struct IClass
*cl
, Object
*obj
, struct MUIP_Draw
*msg
)
1534 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1538 BOOL scroll_caused_damage
= FALSE
;
1539 struct MUI_ImageSpec_intern
*highlight
;
1542 if (data
->flags
& LIST_QUIET
)
1545 ret
= DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1547 if (data
->area_replaced
)
1550 /* Calculate the title height */
1553 data
->title_height
= data
->entries
[ENTRY_TITLE
]->height
+ 2;
1557 data
->title_height
= 0;
1560 /* Calc the numbers of entries visible */
1561 CalcVertVisible(cl
, obj
);
1563 if ((msg
->flags
& MADF_DRAWUPDATE
) == 0 || data
->update
== 1)
1565 DoMethod(obj
, MUIM_DrawBackground
, _mleft(data
->area
), _mtop(data
->area
),
1566 _mwidth(data
->area
), _mheight(data
->area
),
1567 0, data
->entries_first
* data
->entry_maxheight
, 0);
1570 clip
= MUI_AddClipping(muiRenderInfo(obj
), _mleft(data
->area
), _mtop(data
->area
),
1571 _mwidth(data
->area
), _mheight(data
->area
));
1573 if ((msg
->flags
& MADF_DRAWUPDATE
) == 0 || data
->update
== 1)
1575 y
= _mtop(data
->area
);
1578 if (data
->title_height
&& data
->title
)
1580 List_DrawEntry(cl
, obj
, ENTRY_TITLE
, y
);
1581 y
+= data
->entries
[ENTRY_TITLE
]->height
;
1582 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
1583 Move(_rp(obj
), _mleft(data
->area
), y
);
1584 Draw(_rp(obj
), _mright(data
->area
), y
);
1585 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
1587 Move(_rp(obj
), _mleft(data
->area
), y
);
1588 Draw(_rp(obj
), _mright(data
->area
), y
);
1592 y
= data
->entries_top_pixel
;
1594 start
= data
->entries_first
;
1595 end
= data
->entries_first
+ data
->entries_visible
;
1597 if ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 3)
1599 int diffy
= data
->entries_first
- data
->update_pos
;
1601 if (abs(diffy
) < data
->entries_visible
)
1603 scroll_caused_damage
=
1604 (_rp(obj
)->Layer
->Flags
& LAYERREFRESH
) ? FALSE
: TRUE
;
1606 ScrollRaster(_rp(obj
), 0, diffy
* data
->entry_maxheight
,
1607 _mleft(data
->area
), y
,
1608 _mright(data
->area
),
1609 y
+ data
->entry_maxheight
* data
->entries_visible
);
1611 scroll_caused_damage
=
1612 scroll_caused_damage
1613 && (_rp(obj
)->Layer
->Flags
& LAYERREFRESH
);
1617 start
= end
- diffy
;
1618 y
+= data
->entry_maxheight
* (data
->entries_visible
-
1622 end
= start
- diffy
;
1626 bottom
= y
+ (end
- start
) * data
->entry_maxheight
;
1628 DoMethod(obj
, MUIM_DrawBackground
, _mleft(data
->area
), top
,
1629 _mwidth(data
->area
), bottom
- top
+ 1,
1631 top
- _mtop(data
->area
) + data
->entries_first
* data
->entry_maxheight
,
1635 for (entry_pos
= start
;
1636 entry_pos
< end
&& entry_pos
< data
->entries_num
; entry_pos
++)
1638 struct ListEntry
*entry
= data
->entries
[entry_pos
];
1640 if (!(msg
->flags
& MADF_DRAWUPDATE
) ||
1641 ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 1) ||
1642 ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 3) ||
1643 ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 2
1644 && data
->update_pos
== entry_pos
))
1646 /* Choose appropriate highlight image */
1648 if (entry_pos
== data
->entries_active
1649 && entry
->flags
& ENTRY_SELECTED
)
1650 highlight
= data
->list_selcur
;
1651 else if (entry_pos
== data
->entries_active
)
1652 highlight
= data
->list_cursor
;
1653 else if (entry
->flags
& ENTRY_SELECTED
)
1654 highlight
= data
->list_select
;
1658 /* Draw highlight or background */
1660 if (highlight
!= NULL
)
1662 zune_imspec_draw(highlight
, muiRenderInfo(obj
),
1663 _mleft(data
->area
), y
, _mwidth(data
->area
), data
->entry_maxheight
,
1664 0, y
- data
->entries_top_pixel
, 0);
1666 else if ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 2
1667 && data
->update_pos
== entry_pos
)
1669 DoMethod(obj
, MUIM_DrawBackground
, _mleft(data
->area
), y
,
1670 _mwidth(data
->area
), data
->entry_maxheight
, 0,
1671 y
- _mtop(data
->area
) +
1672 data
->entries_first
* data
->entry_maxheight
, 0);
1675 List_DrawEntry(cl
, obj
, entry_pos
, y
);
1677 y
+= data
->entry_maxheight
;
1680 MUI_RemoveClipping(muiRenderInfo(obj
), clip
);
1684 if (scroll_caused_damage
)
1686 if (MUI_BeginRefresh(muiRenderInfo(obj
), 0))
1688 /* Theoretically it might happen that more damage is caused
1689 after ScrollRaster. By something else, like window movement
1690 in front of our window. Therefore refresh root object of
1691 window, not just this object */
1695 get(_win(obj
), MUIA_Window_RootObject
, &o
);
1696 MUI_Redraw(o
, MADF_DRAWOBJECT
);
1698 MUI_EndRefresh(muiRenderInfo(obj
), 0);
1702 ULONG x1
= _mleft(data
->area
);
1704 y
= _mtop(data
->area
);
1706 if (data
->title_height
&& data
->title
)
1708 for (col
= 0; col
< data
->columns
; col
++)
1710 ULONG halfdelta
= data
->ci
[col
].delta
/ 2;
1711 x1
+= data
->ci
[col
].entries_width
+ halfdelta
;
1713 if (x1
+ (data
->ci
[col
].bar
? BAR_WIDTH
: 0) > _mright(data
->area
))
1716 if (data
->ci
[col
].bar
)
1718 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
1719 Move(_rp(obj
), x1
, y
);
1721 y
+ data
->entries
[ENTRY_TITLE
]->height
- 1);
1722 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
1723 Move(_rp(obj
), x1
+ 1, y
);
1724 Draw(_rp(obj
), x1
+ 1,
1725 y
+ data
->entries
[ENTRY_TITLE
]->height
- 1);
1729 x1
+= data
->ci
[col
].delta
- halfdelta
;
1731 y
+= data
->entries
[ENTRY_TITLE
]->height
+ 1;
1734 x1
= _mleft(data
->area
);
1736 for (col
= 0; col
< data
->columns
; col
++)
1738 ULONG halfdelta
= data
->ci
[col
].delta
/ 2;
1739 x1
+= data
->ci
[col
].entries_width
+ halfdelta
;
1741 if (x1
+ (data
->ci
[col
].bar
? BAR_WIDTH
: 0) > _mright(data
->area
))
1744 if (data
->ci
[col
].bar
)
1746 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
1747 Move(_rp(obj
), x1
, y
);
1748 Draw(_rp(obj
), x1
, _mbottom(data
->area
));
1749 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
1750 Move(_rp(obj
), x1
+ 1, y
);
1751 Draw(_rp(obj
), x1
+ 1, _mbottom(data
->area
));
1756 x1
+= data
->ci
[col
].delta
- halfdelta
;
1762 /****** List.mui/MUIM_List_Clear *********************************************
1765 * MUIM_List_Clear (V4)
1768 * DoMethod(obj, MUIM_List_Clear);
1771 * Removes all entries from the list.
1773 ******************************************************************************
1777 IPTR
List__MUIM_Clear(struct IClass
*cl
, Object
*obj
,
1778 struct MUIP_List_Clear
*msg
)
1780 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1782 while (data
->confirm_entries_num
)
1784 struct ListEntry
*lentry
=
1785 data
->entries
[--data
->confirm_entries_num
];
1786 DoMethod(obj
, MUIM_List_Destruct
, (IPTR
) lentry
->data
,
1788 FreeListEntry(data
, lentry
);
1790 /* Should never fail when shrinking */
1791 SetListSize(data
, 0);
1794 if (data
->confirm_entries_num
!= data
->entries_num
)
1796 SetAttrs(obj
, MUIA_List_Entries
, 0, MUIA_List_First
, 0,
1797 /* Notify only when no entry was active */
1798 data
->entries_active
!=
1799 MUIV_List_Active_Off
? MUIA_List_Active
: TAG_DONE
,
1800 MUIV_List_Active_Off
, TAG_DONE
);
1803 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1809 /**************************************************************************
1811 **************************************************************************/
1812 IPTR
List__MUIM_Exchange(struct IClass
*cl
, Object
*obj
,
1813 struct MUIP_List_Exchange
*msg
)
1815 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1820 case MUIV_List_Exchange_Top
:
1823 case MUIV_List_Exchange_Active
:
1824 pos1
= data
->entries_active
;
1826 case MUIV_List_Exchange_Bottom
:
1827 pos1
= data
->entries_num
- 1;
1835 case MUIV_List_Exchange_Top
:
1838 case MUIV_List_Exchange_Active
:
1839 pos2
= data
->entries_active
;
1841 case MUIV_List_Exchange_Bottom
:
1842 pos2
= data
->entries_num
- 1;
1844 case MUIV_List_Exchange_Next
:
1847 case MUIV_List_Exchange_Previous
:
1854 if (pos1
>= 0 && pos1
< data
->entries_num
&& pos2
>= 0
1855 && pos2
< data
->entries_num
&& pos1
!= pos2
)
1857 struct ListEntry
*save
= data
->entries
[pos1
];
1858 data
->entries
[pos1
] = data
->entries
[pos2
];
1859 data
->entries
[pos2
] = save
;
1862 data
->update_pos
= pos1
;
1863 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1866 data
->update_pos
= pos2
;
1867 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1877 /**************************************************************************
1879 **************************************************************************/
1880 IPTR
List__MUIM_Redraw(struct IClass
*cl
, Object
*obj
,
1881 struct MUIP_List_Redraw
*msg
)
1883 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1885 if (!(data
->flags
& LIST_QUIET
))
1887 if (msg
->pos
== MUIV_List_Redraw_All
)
1890 CalcWidths(cl
, obj
);
1891 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1896 if (msg
->pos
== MUIV_List_Redraw_Active
)
1897 pos
= data
->entries_active
;
1898 else if (msg
->pos
== MUIV_List_Redraw_Entry
)
1901 for (i
= 0; i
< data
->entries_num
; i
++)
1902 if (data
->entries
[i
]->data
== msg
->entry
)
1913 if (CalcDimsOfEntry(cl
, obj
, pos
))
1918 data
->update_pos
= pos
;
1920 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1927 /**************************************************************************
1929 **************************************************************************/
1930 IPTR
List__MUIM_Remove(struct IClass
*cl
, Object
*obj
,
1931 struct MUIP_List_Remove
*msg
)
1933 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1936 struct ListEntry
*lentry
;
1937 //int rem_count = 1;
1939 if (!data
->entries_num
)
1944 case MUIV_List_Remove_First
:
1948 case MUIV_List_Remove_Active
:
1949 pos
= data
->entries_active
;
1952 case MUIV_List_Remove_Last
:
1953 pos
= data
->entries_num
- 1;
1956 case MUIV_List_Remove_Selected
:
1957 /* TODO: needs special handling */
1958 pos
= data
->entries_active
;
1966 if (pos
< 0 || pos
>= data
->entries_num
)
1969 new_act
= data
->entries_active
;
1971 if (pos
== new_act
&& new_act
== data
->entries_num
- 1)
1972 new_act
--; /* might become MUIV_List_Active_Off */
1974 lentry
= data
->entries
[pos
];
1975 DoMethod(obj
, MUIM_List_Destruct
, (IPTR
) lentry
->data
,
1980 RemoveListEntries(data
, pos
, cur
- pos
);
1981 data
->confirm_entries_num
-= cur
- pos
;
1983 /* ensure that the active element is in a valid range */
1984 if (new_act
>= data
->entries_num
)
1985 new_act
= data
->entries_num
- 1;
1987 SetAttrs(obj
, MUIA_List_Entries
, data
->confirm_entries_num
,
1988 (new_act
>= pos
) || (new_act
!= data
->entries_active
) ?
1989 MUIA_List_Active
: TAG_DONE
,
1990 new_act
, /* Inform only if neccessary (for notify) */
1994 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1999 /**************************************************************************
2001 **************************************************************************/
2002 IPTR
List__MUIM_Select(struct IClass
*cl
, Object
*obj
,
2003 struct MUIP_List_Select
*msg
)
2005 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2006 LONG pos
, i
, count
, selcount
=0, state
=0;
2007 BOOL multi_allowed
= TRUE
, new_select_state
= FALSE
;
2009 /* Establish the range of entries affected */
2012 case MUIV_List_Select_Active
:
2013 pos
= data
->entries_active
;
2014 if (pos
== MUIV_List_Active_Off
)
2020 case MUIV_List_Select_All
:
2022 count
= data
->entries_num
;
2028 if (pos
< 0 || pos
>= data
->entries_num
)
2033 if (msg
->seltype
!= MUIV_List_Select_Ask
&& data
->multi_test_hook
!= NULL
)
2035 /* Disallow selection of an additional entry if there is a currently
2036 selected entry that is not multi-selectable (in such case there
2037 will only be one entry currently selected, so no need to iterate) */
2038 i
= MUIV_List_NextSelected_Start
;
2039 DoMethod(obj
, MUIM_List_NextSelected
, (IPTR
) &i
);
2040 if (i
!= MUIV_List_NextSelected_End
)
2042 if (data
->multi_test_hook
!= NULL
&& selcount
!= 0)
2043 multi_allowed
= CallHookPkt(data
->multi_test_hook
, NULL
,
2044 data
->entries
[i
]->data
);
2047 /* Change or check state of each entry in the range */
2048 for (i
= pos
; i
< pos
+ count
; i
++)
2050 state
= data
->entries
[i
]->flags
& ENTRY_SELECTED
;
2051 switch (msg
->seltype
)
2053 case MUIV_List_Select_Off
:
2054 new_select_state
= FALSE
;
2057 case MUIV_List_Select_On
:
2058 new_select_state
= TRUE
;
2061 case MUIV_List_Select_Toggle
:
2062 new_select_state
= !state
;
2066 if (data
->entries
[i
]->flags
& ENTRY_SELECTED
)
2071 if (msg
->seltype
!= MUIV_List_Select_Ask
)
2073 /* Disallow selection if entry is not multi-selectable and
2074 * there are already selected entries */
2075 if (data
->multi_test_hook
!= NULL
&& new_select_state
)
2076 new_select_state
= multi_allowed
&& (selcount
== 0 ||
2077 CallHookPkt(data
->multi_test_hook
, NULL
,
2078 data
->entries
[i
]->data
));
2080 if (new_select_state
)
2081 data
->entries
[i
]->flags
|= ENTRY_SELECTED
;
2083 data
->entries
[i
]->flags
&= ~ENTRY_SELECTED
;
2087 /* Report old state or number of selected entries */
2090 if (msg
->pos
== MUIV_List_Select_All
2091 && msg
->seltype
== MUIV_List_Select_Ask
)
2092 *msg
->info
= selcount
;
2097 /* Redraw unless it was just an enquiry */
2098 if (msg
->seltype
!= MUIV_List_Select_Ask
)
2105 data
->update_pos
= pos
;
2107 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2113 /**************************************************************************
2115 **************************************************************************/
2117 IPTR
List__MUIM_Insert(struct IClass
*cl
, Object
*obj
,
2118 struct MUIP_List_Insert
*msg
)
2120 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2121 LONG pos
, count
, sort
;
2128 /* Count the number of entries */
2129 for (count
= 0; msg
->entries
[count
] != NULL
; count
++)
2138 case MUIV_List_Insert_Top
:
2142 case MUIV_List_Insert_Active
:
2143 if (data
->entries_active
!= -1)
2144 pos
= data
->entries_active
;
2149 case MUIV_List_Insert_Sorted
:
2150 pos
= data
->entries_num
;
2151 sort
= 1; /* we sort'em later */
2154 case MUIV_List_Insert_Bottom
:
2155 pos
= data
->entries_num
;
2159 if (msg
->pos
> data
->entries_num
)
2160 pos
= data
->entries_num
;
2161 else if (msg
->pos
< 0)
2168 if (!(SetListSize(data
, data
->entries_num
+ count
)))
2171 LONG until
= pos
+ count
;
2172 APTR
*toinsert
= msg
->entries
;
2174 if (!(PrepareInsertListEntries(data
, pos
, count
)))
2179 struct ListEntry
*lentry
;
2181 if (!(lentry
= AllocListEntry(data
)))
2183 /* Panic, but we must be in a consistent state, so remove
2184 * the space where the following list entries should have gone
2186 RemoveListEntries(data
, pos
, until
- pos
);
2190 /* now call the construct method which returns us a pointer which
2192 lentry
->data
= (APTR
) DoMethod(obj
, MUIM_List_Construct
,
2193 (IPTR
) * toinsert
, (IPTR
) data
->pool
);
2196 FreeListEntry(data
, lentry
);
2197 RemoveListEntries(data
, pos
, until
- pos
);
2199 /* TODO: Also check for visible stuff like below */
2200 if (data
->entries_num
!= data
->confirm_entries_num
)
2201 set(obj
, MUIA_List_Entries
, data
->confirm_entries_num
);
2205 data
->entries
[pos
] = lentry
;
2206 data
->confirm_entries_num
++;
2208 if (_flags(obj
) & MADF_SETUP
)
2210 /* We have to calculate the width and height of the newly
2211 * inserted entry. This has to be done after inserting the
2212 * element into the list */
2213 CalcDimsOfEntry(cl
, obj
, pos
);
2220 /* Recalculate the number of visible entries */
2221 if (_flags(obj
) & MADF_SETUP
)
2222 CalcVertVisible(cl
, obj
);
2224 if (data
->entries_num
!= data
->confirm_entries_num
)
2227 MUIA_List_Entries
, data
->confirm_entries_num
,
2228 MUIA_List_Visible
, data
->entries_visible
, TAG_DONE
);
2231 /* If the array is already sorted, we could do a simple insert
2232 * sort and would be much faster than with qsort.
2233 * If an array is not yet sorted, does a MUIV_List_Insert_Sorted
2234 * sort the whole array?
2236 * I think, we better sort the whole array:
2240 DoMethod(obj
, MUIM_List_Sort
);
2241 /* TODO: which pos to return here !? */
2242 /* MUIM_List_Sort already called MUI_Redraw */
2247 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2249 data
->insert_position
= pos
;
2254 /**************************************************************************
2255 MUIM_List_InsertSingle
2256 **************************************************************************/
2257 IPTR
List__MUIM_InsertSingle(struct IClass
*cl
, Object
*obj
,
2258 struct MUIP_List_InsertSingle
*msg
)
2260 return DoMethod(obj
, MUIM_List_Insert
, (IPTR
) & msg
->entry
, 1,
2264 /**************************************************************************
2266 **************************************************************************/
2267 IPTR
List__MUIM_GetEntry(struct IClass
*cl
, Object
*obj
,
2268 struct MUIP_List_GetEntry
*msg
)
2270 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2273 if (pos
== MUIV_List_GetEntry_Active
)
2274 pos
= data
->entries_active
;
2276 if (pos
< 0 || pos
>= data
->entries_num
)
2281 *msg
->entry
= data
->entries
[pos
]->data
;
2282 return (IPTR
) *msg
->entry
;
2285 /**************************************************************************
2287 **************************************************************************/
2288 IPTR
List__MUIM_Construct(struct IClass
*cl
, Object
*obj
,
2289 struct MUIP_List_Construct
*msg
)
2291 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2293 if (NULL
== data
->construct_hook
)
2294 return (IPTR
) msg
->entry
;
2295 if ((IPTR
) data
->construct_hook
== MUIV_List_ConstructHook_String
)
2297 int len
= msg
->entry
? strlen((STRPTR
) msg
->entry
) : 0;
2298 ULONG
*mem
= AllocPooled(msg
->pool
, len
+ 5);
2303 if (msg
->entry
!= NULL
)
2304 strcpy((STRPTR
) (mem
+ 1), (STRPTR
) msg
->entry
);
2306 *(STRPTR
) (mem
+ 1) = 0;
2307 return (IPTR
) (mem
+ 1);
2309 return CallHookPkt(data
->construct_hook
, msg
->pool
, msg
->entry
);
2312 /**************************************************************************
2314 **************************************************************************/
2315 IPTR
List__MUIM_Destruct(struct IClass
*cl
, Object
*obj
,
2316 struct MUIP_List_Destruct
*msg
)
2318 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2320 if (NULL
== data
->destruct_hook
)
2323 if ((IPTR
) data
->destruct_hook
== MUIV_List_DestructHook_String
)
2325 ULONG
*mem
= ((ULONG
*) msg
->entry
) - 1;
2326 FreePooled(msg
->pool
, mem
, mem
[0]);
2330 CallHookPkt(data
->destruct_hook
, msg
->pool
, msg
->entry
);
2335 /****** List.mui/MUIM_List_Compare *******************************************
2338 * MUIM_List_Compare (V20)
2341 * DoMethod(obj, MUIM_List_Compare, APTR entry1, APTR entry2,
2342 * LONG sort_type1, LONG sort_type2);
2345 * Compare two list entries according to the current comparison hook
2346 * (MUIA_List_CompareHook).
2349 * entry1 - the first entry data.
2350 * entry2 - the second entry data.
2351 * sort_type1 - undocumented.
2352 * sort_type2 - undocumented.
2355 * MUIA_List_CompareHook, MUIM_List_Sort.
2357 ******************************************************************************
2361 IPTR
List__MUIM_Compare(struct IClass
*cl
, Object
*obj
,
2362 struct MUIP_List_Compare
*msg
)
2364 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2366 return CallHookPkt(data
->compare_hook
, msg
->entry2
, msg
->entry1
);
2369 /**************************************************************************
2371 **************************************************************************/
2372 IPTR
List__MUIM_Display(struct IClass
*cl
, Object
*obj
,
2373 struct MUIP_List_Display
*msg
)
2375 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2377 if (NULL
== data
->display_hook
)
2380 *msg
->array
= msg
->entry
;
2386 *((ULONG
*) (msg
->array
- 1)) = msg
->entry_pos
;
2387 return CallHookPkt(data
->display_hook
, msg
->array
, msg
->entry
);
2390 /**************************************************************************
2391 MUIM_List_SelectChange
2392 **************************************************************************/
2393 IPTR
List__MUIM_SelectChange(struct IClass
*cl
, Object
*obj
,
2394 struct MUIP_List_SelectChange
*msg
)
2399 /**************************************************************************
2400 MUIM_List_CreateImage
2401 Called by a List subclass in its Setup method.
2402 Connects an Area subclass object to the list, much like an object gets
2403 connected to a window. List calls Setup and AskMinMax on that object,
2404 keeps a reference to it (that reference will be returned).
2405 Text engine will dereference that pointer and draw the object with its
2407 **************************************************************************/
2408 IPTR
List__MUIM_CreateImage(struct IClass
*cl
, Object
*obj
,
2409 struct MUIP_List_CreateImage
*msg
)
2411 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2412 struct ListImage
*li
;
2417 /* List must be already setup in Setup of your subclass */
2418 if (!(_flags(obj
) & MADF_SETUP
))
2420 li
= AllocPooled(data
->pool
, sizeof(struct ListImage
));
2425 AddTail((struct List
*)&data
->images
, (struct Node
*)li
);
2426 DoMethod(li
->obj
, MUIM_ConnectParent
, (IPTR
) obj
);
2427 DoSetupMethod(li
->obj
, muiRenderInfo(obj
));
2433 /**************************************************************************
2434 MUIM_List_DeleteImage
2435 **************************************************************************/
2436 IPTR
List__MUIM_DeleteImage(struct IClass
*cl
, Object
*obj
,
2437 struct MUIP_List_DeleteImage
*msg
)
2439 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2440 struct ListImage
*li
= (struct ListImage
*)msg
->listimg
;
2444 DoMethod(li
->obj
, MUIM_Cleanup
);
2445 DoMethod(li
->obj
, MUIM_DisconnectParent
);
2446 Remove((struct Node
*)li
);
2447 FreePooled(data
->pool
, li
, sizeof(struct ListImage
));
2453 /****** List.mui/MUIM_List_Jump **********************************************
2456 * MUIM_List_Jump (V4)
2459 * DoMethod(obj, MUIM_List_Jump, LONG pos);
2462 * Scrolls the list so that a particular entry is visible.
2465 * pos - index of entry that should become visible, or one of these
2467 * MUIV_List_Jump_Active: show the active entry.
2468 * MUIV_List_Jump_Top: show the first entry.
2469 * MUIV_List_Jump_Bottom: show the last entry.
2470 * MUIV_List_Jump_Up: show the previous hidden entry.
2471 * MUIV_List_Jump_Down: show the next hidden entry.
2473 ******************************************************************************
2477 IPTR
List__MUIM_Jump(struct IClass
*cl
, Object
*obj
,
2478 struct MUIP_List_Jump
*msg
)
2480 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2481 LONG pos
= msg
->pos
;
2485 case MUIV_List_Jump_Top
:
2489 case MUIV_List_Jump_Active
:
2490 pos
= data
->entries_active
;
2493 case MUIV_List_Jump_Bottom
:
2494 pos
= data
->entries_num
- 1;
2497 case MUIV_List_Jump_Down
:
2498 pos
= data
->entries_first
+ data
->entries_visible
;
2501 case MUIV_List_Jump_Up
:
2502 pos
= data
->entries_first
- 1;
2506 if (pos
>= data
->entries_num
)
2508 pos
= data
->entries_num
- 1;
2513 if (pos
< data
->entries_first
)
2515 set(obj
, MUIA_List_First
, pos
);
2517 else if (pos
>= data
->entries_first
+ data
->entries_visible
)
2519 pos
-= (data
->entries_visible
- 1);
2522 if (pos
!= data
->entries_first
)
2524 set(obj
, MUIA_List_First
, pos
);
2531 /****** List.mui/MUIM_List_Sort **********************************************
2534 * MUIM_List_Sort (V4)
2537 * DoMethod(obj, MUIM_List_Sort);
2540 * Sort the list's entries according to the current comparison hook
2541 * (MUIA_List_CompareHook).
2544 * MUIA_List_CompareHook, MUIM_List_Compare.
2546 ******************************************************************************
2550 IPTR
List__MUIM_Sort(struct IClass
*cl
, Object
*obj
,
2551 struct MUIP_List_Sort
*msg
)
2553 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2556 struct MUIP_List_Compare cmpmsg
=
2557 { MUIM_List_Compare
, NULL
, NULL
, 0, 0 };
2559 if (data
->entries_num
> 1)
2562 Simple sort algorithm. Feel free to improve it.
2564 for (i
= 0; i
< data
->entries_num
- 1; i
++)
2567 for (j
= i
+ 1; j
< data
->entries_num
; j
++)
2569 cmpmsg
.entry1
= data
->entries
[max
]->data
;
2570 cmpmsg
.entry2
= data
->entries
[j
]->data
;
2571 if ((LONG
) DoMethodA(obj
, (Msg
) & cmpmsg
) > 0)
2578 APTR tmp
= data
->entries
[i
];
2579 data
->entries
[i
] = data
->entries
[max
];
2580 data
->entries
[max
] = tmp
;
2586 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2591 /****** List.mui/MUIM_List_Move **********************************************
2594 * MUIM_List_Move (V9)
2597 * DoMethod(obj, MUIM_List_Move, LONG from, LONG to);
2600 * Move a list entry to a new position.
2603 * from - the current index of the entry that should be moved, or one of
2604 * these special values:
2605 * MUIV_List_Move_Active: the active entry.
2606 * MUIV_List_Move_Top: the first entry.
2607 * MUIV_List_Move_Bottom: the last entry.
2608 * to - the index of the entry's new position, or one of
2609 * these special values:
2610 * MUIV_List_Move_Active: the active entry.
2611 * MUIV_List_Move_Top: the first entry.
2612 * MUIV_List_Move_Bottom: the last entry.
2614 ******************************************************************************
2618 IPTR
List__MUIM_Move(struct IClass
*cl
, Object
*obj
,
2619 struct MUIP_List_Move
*msg
)
2621 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2626 /* Normalise special 'from' values */
2629 case MUIV_List_Move_Top
:
2632 case MUIV_List_Move_Active
:
2633 from
= data
->entries_active
;
2635 case MUIV_List_Move_Bottom
:
2636 from
= data
->entries_num
- 1;
2642 /* Normalise special 'to' values */
2645 case MUIV_List_Move_Top
:
2648 case MUIV_List_Move_Active
:
2649 to
= data
->entries_active
;
2651 case MUIV_List_Move_Bottom
:
2652 to
= data
->entries_num
- 1;
2654 case MUIV_List_Move_Next
:
2657 case MUIV_List_Move_Previous
:
2664 /* Check that values are within valid bounds */
2665 if (from
> data
->entries_num
- 1 || from
< 0
2666 || to
> data
->entries_num
- 1 || to
< 0 || from
== to
)
2667 return (IPTR
) FALSE
;
2669 /* Shift all entries in the range between the 'from' and 'to' positions */
2672 struct ListEntry
*backup
= data
->entries
[from
];
2673 for (i
= from
; i
< to
; i
++)
2674 data
->entries
[i
] = data
->entries
[i
+ 1];
2675 data
->entries
[to
] = backup
;
2679 struct ListEntry
*backup
= data
->entries
[from
];
2680 for (i
= from
; i
> to
; i
--)
2681 data
->entries
[i
] = data
->entries
[i
- 1];
2682 data
->entries
[to
] = backup
;
2685 /* Update index of active entry */
2686 if (from
== data
->entries_active
)
2687 data
->entries_active
= to
;
2688 else if (data
->entries_active
> from
&& data
->entries_active
< to
)
2689 data
->entries_active
--;
2690 else if (data
->entries_active
< from
&& data
->entries_active
>= to
)
2691 data
->entries_active
++;
2693 /* Reflect list changes visually */
2695 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2700 /**************************************************************************
2701 MUIM_List_NextSelected
2702 **************************************************************************/
2703 IPTR
List__MUIM_NextSelected(struct IClass
*cl
, Object
*obj
,
2704 struct MUIP_List_NextSelected
*msg
)
2706 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2710 /* Get the first entry to check */
2712 if (pos
== MUIV_List_NextSelected_Start
)
2717 /* Find the next selected entry */
2718 for (i
= pos
; i
< data
->entries_num
&& !found
; i
++)
2720 if (data
->entries
[i
]->flags
& ENTRY_SELECTED
)
2727 /* Return index of selected entry, or indicate there are no more */
2729 pos
= MUIV_List_NextSelected_End
;
2735 /**************************************************************************
2737 **************************************************************************/
2738 IPTR
List__MUIM_TestPos(struct IClass
*cl
, Object
*obj
,
2739 struct MUIP_List_TestPos
*msg
)
2741 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2742 struct MUI_List_TestPos_Result
*result
= msg
->res
;
2743 LONG col
= -1, row
= -1;
2745 LONG mx
= msg
->x
- _left(data
->area
);
2746 LONG entries_visible
;
2748 if (data
->entries_visible
<= data
->entries_num
)
2749 entries_visible
= data
->entries_visible
;
2751 entries_visible
= data
->entries_num
;
2752 LONG ey
= msg
->y
- data
->entries_top_pixel
;
2753 /* y coordinates transformed to the entries */
2755 /* Now check if it was clicked on a title or on entries */
2757 flags
|= MUI_LPR_ABOVE
;
2758 else if (ey
>= entries_visible
* data
->entry_maxheight
)
2759 flags
|= MUI_LPR_BELOW
;
2763 row
= ey
/ data
->entry_maxheight
+ data
->entries_first
;
2765 ey
% data
->entry_maxheight
- data
->entry_maxheight
/ 2;
2769 flags
|= MUI_LPR_LEFT
;
2770 else if (mx
>= _width(data
->area
))
2771 flags
|= MUI_LPR_RIGHT
;
2774 /* Identify column */
2775 if (data
->entries_num
> 0 && data
->columns
> 0)
2778 col
= data
->columns
- 1;
2779 for (i
= 0; i
< data
->columns
; i
++)
2781 result
->xoffset
= mx
- width_sum
;
2783 data
->ci
[i
].entries_width
+
2785 (data
->ci
[i
].bar
? BAR_WIDTH
: 0);
2786 D(bug("[List/MUIM_TestPos] i %d "
2787 "width %d width_sum %d mx %d\n",
2788 i
, data
->ci
[i
].entries_width
, width_sum
, mx
));
2792 D(bug("[List/MUIM_TestPos] Column hit %d\n", col
));
2799 result
->entry
= row
;
2800 result
->column
= col
;
2801 result
->flags
= flags
;
2806 /****i* List.mui/MUIM_DragQuery **********************************************
2811 ******************************************************************************
2815 IPTR
List__MUIM_DragQuery(struct IClass
*cl
, Object
*obj
,
2816 struct MUIP_DragQuery
*msg
)
2818 if (msg
->obj
== obj
)
2819 return MUIV_DragQuery_Accept
;
2821 return MUIV_DragQuery_Refuse
;
2825 /****i* List.mui/MUIM_DragFinish *********************************************
2830 ******************************************************************************
2834 IPTR
List__MUIM_DragFinish(struct IClass
*cl
, Object
*obj
,
2835 struct MUIP_DragFinish
*msg
)
2837 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2839 data
->drop_mark_y
= -1;
2841 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
2844 /****i* List.mui/MUIM_DragReport *********************************************
2849 ******************************************************************************
2853 IPTR
List__MUIM_DragReport(struct IClass
*cl
, Object
*obj
,
2854 struct MUIP_DragReport
*msg
)
2856 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2857 struct MUI_List_TestPos_Result pos
;
2858 struct RastPort
*rp
= _rp(obj
);
2862 /* Choose new drop mark position */
2864 DoMethod(obj
, MUIM_List_TestPos
, msg
->x
, msg
->y
, (IPTR
) &pos
);
2865 if (pos
.entry
!= -1)
2868 if (pos
.yoffset
> 0)
2871 else if ((pos
.flags
& MUI_LPR_ABOVE
) != 0)
2872 n
= data
->entries_first
;
2875 n
= MIN(data
->entries_visible
, data
->entries_num
)
2876 - data
->entries_first
;
2879 /* Clear old drop mark */
2881 if ((data
->flags
& LIST_SHOWDROPMARKS
) != 0)
2883 y
= data
->entries_top_pixel
+ (n
- data
->entries_first
)
2884 * data
->entry_maxheight
;
2885 if (y
!= data
->drop_mark_y
)
2887 DoMethod(obj
, MUIM_DrawBackground
, _mleft(data
->area
), data
->drop_mark_y
,
2888 _mwidth(data
->area
), 1, 0, 0, 0);
2890 /* Draw new drop mark and store its position */
2892 SetABPenDrMd(rp
, _pens(obj
)[MPEN_SHINE
], _pens(obj
)[MPEN_SHADOW
],
2894 old_pattern
= rp
->LinePtrn
;
2895 SetDrPt(rp
, 0xF0F0);
2896 Move(rp
, _mleft(data
->area
), y
);
2897 Draw(rp
, _mright(data
->area
), y
);
2898 SetDrPt(rp
, old_pattern
);
2899 data
->drop_mark_y
= y
;
2907 /****i* List.mui/MUIM_DragDrop ***********************************************
2912 ******************************************************************************
2916 IPTR
List__MUIM_DragDrop(struct IClass
*cl
, Object
*obj
,
2917 struct MUIP_DragDrop
*msg
)
2919 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2920 struct MUI_List_TestPos_Result pos
;
2923 /* Find drop position */
2925 DoMethod(obj
, MUIM_List_TestPos
, msg
->x
, msg
->y
, (IPTR
) &pos
);
2926 if (pos
.entry
!= -1)
2928 /* Change drop position when coords move past centre of entry, not
2932 if (pos
.yoffset
> 0)
2935 /* Ensure that dropped entry will be positioned between the two
2936 * entries that are above and below the drop mark, rather than
2937 * strictly at the numeric index shown */
2939 if (n
> data
->entries_active
)
2942 else if ((pos
.flags
& MUI_LPR_ABOVE
) != 0)
2943 n
= MUIV_List_Move_Top
;
2945 n
= MUIV_List_Move_Bottom
;
2947 DoMethod(msg
->obj
, MUIM_List_Move
, MUIV_List_Move_Active
, n
);
2953 /****i* List.mui/MUIM_CreateDragImage ****************************************
2956 * MUIM_CreateDragImage
2958 ******************************************************************************
2962 static IPTR
List__MUIM_CreateDragImage(struct IClass
*cl
, Object
*obj
,
2963 struct MUIP_CreateDragImage
*msg
)
2965 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2966 BOOL success
= TRUE
;
2967 struct MUI_List_TestPos_Result pos
;
2968 WORD width
, height
, left
, top
;
2969 struct MUI_DragImage
*img
= NULL
;
2970 const struct ZuneFrameGfx
*zframe
;
2973 /* Get info on dragged entry */
2974 DoMethod(obj
, MUIM_List_TestPos
, _left(data
->area
) - msg
->touchx
,
2975 _top(data
->area
) - msg
->touchy
, (IPTR
) &pos
);
2976 if (pos
.entry
== -1)
2981 /* Get boundaries of entry */
2982 width
= _mwidth(data
->area
);
2983 height
= data
->entry_maxheight
;
2984 left
= _mleft(data
->area
);
2985 top
= _top(data
->area
) - msg
->touchy
2986 - (pos
.yoffset
+ data
->entry_maxheight
/ 2);
2988 /* Allocate drag image structure */
2989 img
= (struct MUI_DragImage
*)
2990 AllocVec(sizeof(struct MUI_DragImage
), MEMF_CLEAR
);
2997 /* Get drag frame */
2998 zframe
= zune_zframe_get(obj
,
2999 &muiGlobalInfo(obj
)->mgi_Prefs
->frames
[MUIV_Frame_Drag
]);
3001 /* Allocate drag image buffer */
3002 img
->width
= width
+ zframe
->ileft
+ zframe
->iright
;
3003 img
->height
= height
+ zframe
->itop
+ zframe
->ibottom
;
3004 depth
= GetBitMapAttr(_screen(obj
)->RastPort
.BitMap
, BMA_DEPTH
);
3005 img
->bm
= AllocBitMap(img
->width
, img
->height
, depth
, BMF_MINPLANES
,
3006 _screen(obj
)->RastPort
.BitMap
);
3008 if (img
->bm
!= NULL
)
3011 struct RastPort temprp
;
3012 InitRastPort(&temprp
);
3013 temprp
.BitMap
= img
->bm
;
3014 ClipBlit(_rp(obj
), left
, top
, &temprp
,
3015 zframe
->ileft
, zframe
->itop
, width
, height
,
3019 struct RastPort
*rp_save
= muiRenderInfo(obj
)->mri_RastPort
;
3020 muiRenderInfo(obj
)->mri_RastPort
= &temprp
;
3021 zframe
->draw(zframe
->customframe
, muiRenderInfo(obj
), 0, 0,
3022 img
->width
, img
->height
, 0, 0, img
->width
, img
->height
);
3023 muiRenderInfo(obj
)->mri_RastPort
= rp_save
;
3026 /* Ensure drag point matches where user clicked */
3027 img
->touchx
= msg
->touchx
- zframe
->ileft
+ _addleft(obj
);
3028 img
->touchy
= -(pos
.yoffset
+ data
->entry_maxheight
/ 2)
3036 static void DoWheelMove(struct IClass
*cl
, Object
*obj
, LONG wheely
)
3038 LONG
new, first
, entries
, visible
;
3040 new = first
= XGET(obj
, MUIA_List_First
);
3041 entries
= XGET(obj
, MUIA_List_Entries
);
3042 visible
= XGET(obj
, MUIA_List_Visible
);
3046 if (new > entries
- visible
)
3048 new = entries
- visible
;
3058 set(obj
, MUIA_List_First
, new);
3062 /**************************************************************************
3064 **************************************************************************/
3065 IPTR
List__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
, struct MUIP_HandleEvent
*msg
)
3067 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
3068 struct MUI_List_TestPos_Result pos
;
3069 LONG seltype
, old_active
, new_active
, visible
, first
, last
, i
;
3071 BOOL select
= FALSE
, clear
= FALSE
, range_select
= FALSE
, changing
;
3073 typeof(msg
->muikey
) muikey
= msg
->muikey
;
3075 new_active
= old_active
= XGET(obj
, MUIA_List_Active
);
3076 visible
= XGET(obj
, MUIA_List_Visible
);
3078 if (muikey
!= MUIKEY_NONE
)
3080 result
= MUI_EventHandlerRC_Eat
;
3082 /* Make keys behave differently in read-only mode */
3083 if (data
->read_only
)
3088 muikey
= MUIKEY_LINESTART
;
3092 muikey
= MUIKEY_LINEEND
;
3096 muikey
= MUIKEY_LEFT
;
3101 muikey
= MUIKEY_RIGHT
;
3109 if (data
->multiselect
!= MUIV_Listview_MultiSelect_None
3110 && !data
->read_only
)
3113 data
->click_column
= data
->def_click_column
;
3114 new_active
= MUIV_List_Active_Down
;
3118 DoMethod(obj
, MUIM_List_Jump
, 0);
3119 muikey
= MUIKEY_NONE
;
3124 new_active
= MUIV_List_Active_Top
;
3128 new_active
= MUIV_List_Active_Bottom
;
3132 case MUIKEY_WORDLEFT
:
3133 DoMethod(obj
, MUIM_List_Jump
, MUIV_List_Jump_Up
);
3137 case MUIKEY_WORDRIGHT
:
3138 DoMethod(obj
, MUIM_List_Jump
, MUIV_List_Jump_Down
);
3141 case MUIKEY_LINESTART
:
3142 DoMethod(obj
, MUIM_List_Jump
, MUIV_List_Jump_Top
);
3145 case MUIKEY_LINEEND
:
3146 DoMethod(obj
, MUIM_List_Jump
, MUIV_List_Jump_Bottom
);
3150 new_active
= MUIV_List_Active_Up
;
3154 new_active
= MUIV_List_Active_Down
;
3158 if (data
->read_only
)
3159 DoWheelMove(cl
, obj
, -visible
);
3161 new_active
= MUIV_List_Active_PageUp
;
3164 case MUIKEY_PAGEDOWN
:
3165 if (data
->read_only
)
3166 DoWheelMove(cl
, obj
, visible
);
3168 new_active
= MUIV_List_Active_PageDown
;
3177 DoMethod(obj
, MUIM_List_TestPos
, msg
->imsg
->MouseX
, msg
->imsg
->MouseY
, (IPTR
) &pos
);
3179 switch (msg
->imsg
->Class
)
3181 case IDCMP_MOUSEBUTTONS
:
3182 if (msg
->imsg
->Code
== SELECTDOWN
)
3184 if (_isinobject(data
->area
, msg
->imsg
->MouseX
, msg
->imsg
->MouseY
))
3186 data
->mouse_click
= MOUSE_CLICK_ENTRY
;
3188 if (!data
->read_only
&& pos
.entry
!= -1)
3190 new_active
= pos
.entry
;
3192 clear
= (data
->multiselect
== MUIV_Listview_MultiSelect_Shifted
3193 && (msg
->imsg
->Qualifier
& (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
)) == 0);
3194 seltype
= clear
? MUIV_List_Select_On
: MUIV_List_Select_Toggle
;
3195 select
= data
->multiselect
!= MUIV_Listview_MultiSelect_None
;
3197 /* Handle MUIA_Listview_ClickColumn */
3198 data
->click_column
= pos
.column
;
3199 superset(cl
, obj
, MUIA_Listview_ClickColumn
,
3200 data
->click_column
);
3202 /* Handle double clicking */
3203 if (data
->last_active
== pos
.entry
3204 && DoubleClick(data
->last_secs
, data
->last_mics
, msg
->imsg
->Seconds
, msg
->imsg
->Micros
))
3206 set(obj
, MUIA_Listview_DoubleClick
, TRUE
);
3207 data
->last_active
= -1;
3208 data
->last_secs
= data
->last_mics
= 0;
3212 data
->last_active
= pos
.entry
;
3213 data
->last_secs
= msg
->imsg
->Seconds
;
3214 data
->last_mics
= msg
->imsg
->Micros
;
3217 /* Look out for mouse movement, timer and
3218 inactive-window events while mouse button is
3220 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) &data
->ehn
);
3221 data
->ehn
.ehn_Events
|= (IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
|IDCMP_INACTIVEWINDOW
);
3222 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) &data
->ehn
);
3228 /* Activate object */
3229 if (msg
->imsg
->Code
== SELECTUP
&& data
->mouse_click
)
3231 set(_win(obj
), MUIA_Window_ActiveObject
, (IPTR
)obj
);
3232 data
->mouse_click
= 0;
3235 /* Restore normal event mask */
3236 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) &data
->ehn
);
3237 data
->ehn
.ehn_Events
&= ~(IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
| IDCMP_INACTIVEWINDOW
);
3238 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) &data
->ehn
);
3242 case IDCMP_MOUSEMOVE
:
3243 case IDCMP_INTUITICKS
:
3244 if (pos
.flags
& MUI_LPR_ABOVE
)
3245 new_active
= MUIV_List_Active_Up
;
3246 else if (pos
.flags
& MUI_LPR_BELOW
)
3247 new_active
= MUIV_List_Active_Down
;
3249 new_active
= pos
.entry
;
3251 select
= new_active
!= old_active
&& data
->multiselect
!= MUIV_Listview_MultiSelect_None
;
3254 DoMethod(obj
, MUIM_List_Select
, MUIV_List_Select_Active
, MUIV_List_Select_Ask
, &seltype
);
3255 range_select
= new_active
>= 0;
3260 case IDCMP_INACTIVEWINDOW
:
3261 /* Stop listening for events we only listen to when mouse button is
3262 down: we will not be informed of the button being released */
3263 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) &data
->ehn
);
3264 data
->ehn
.ehn_Events
&= ~(IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
| IDCMP_INACTIVEWINDOW
);
3265 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) &data
->ehn
);
3270 if (_isinobject(data
->vert
, msg
->imsg
->MouseX
, msg
->imsg
->MouseY
))
3272 else if (_isinobject(data
->area
, msg
->imsg
->MouseX
, msg
->imsg
->MouseY
))
3279 switch (msg
->imsg
->Code
)
3281 case RAWKEY_NM_WHEEL_UP
:
3282 DoWheelMove(cl
, obj
, -delta
);
3285 case RAWKEY_NM_WHEEL_DOWN
:
3286 DoWheelMove(cl
, obj
, delta
);
3289 result
= MUI_EventHandlerRC_Eat
;
3295 /* Decide in advance if any selections may change */
3296 changing
= clear
|| muikey
== MUIKEY_TOGGLE
|| select
;
3298 /* Change selected and active entries */
3300 set(obj
, MUIA_Listview_SelectChange
, TRUE
);
3304 DoMethod(obj
, MUIM_List_Select
, MUIV_List_Select_All
, MUIV_List_Select_Off
, NULL
);
3307 if (muikey
== MUIKEY_TOGGLE
)
3309 DoMethod(obj
, MUIM_List_Select
, MUIV_List_Select_Active
, MUIV_List_Select_Toggle
, NULL
);
3313 if (new_active
!= old_active
)
3314 set(obj
, MUIA_List_Active
, new_active
);
3320 if (old_active
< new_active
)
3321 first
= old_active
+ 1, last
= new_active
;
3323 first
= new_active
, last
= old_active
- 1;
3324 for (i
= first
; i
<= last
; i
++)
3325 DoMethod(obj
, MUIM_List_Select
, i
, seltype
, NULL
);
3328 DoMethod(obj
, MUIM_List_Select
, MUIV_List_Select_Active
, seltype
, NULL
);
3332 set(obj
, MUIA_Listview_SelectChange
, FALSE
);
3337 /**************************************************************************
3339 **************************************************************************/
3340 BOOPSI_DISPATCHER(IPTR
, List_Dispatcher
, cl
, obj
, msg
)
3342 switch (msg
->MethodID
)
3345 return List__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
3347 return List__OM_DISPOSE(cl
, obj
, msg
);
3349 return List__OM_SET(cl
, obj
, (struct opSet
*)msg
);
3351 return List__OM_GET(cl
, obj
, (struct opGet
*)msg
);
3354 return List__MUIM_Setup(cl
, obj
, (struct MUIP_Setup
*)msg
);
3356 return List__MUIM_Cleanup(cl
, obj
, (struct MUIP_Cleanup
*)msg
);
3357 case MUIM_HandleEvent
:
3358 return List__MUIM_HandleEvent(cl
, obj
, (struct MUIP_HandleEvent
*)msg
);
3359 case MUIM_AskMinMax
:
3360 return List__MUIM_AskMinMax(cl
, obj
, (struct MUIP_AskMinMax
*)msg
);
3362 return List__MUIM_Show(cl
, obj
, (struct MUIP_Show
*)msg
);
3364 return List__MUIM_Hide(cl
, obj
, (struct MUIP_Hide
*)msg
);
3366 return List__MUIM_Draw(cl
, obj
, (struct MUIP_Draw
*)msg
);
3368 return List__MUIM_Layout(cl
, obj
, (struct MUIP_Layout
*)msg
);
3369 case MUIM_List_Clear
:
3370 return List__MUIM_Clear(cl
, obj
, (struct MUIP_List_Clear
*)msg
);
3371 case MUIM_List_Sort
:
3372 return List__MUIM_Sort(cl
, obj
, (struct MUIP_List_Sort
*)msg
);
3373 case MUIM_List_Exchange
:
3374 return List__MUIM_Exchange(cl
, obj
,
3375 (struct MUIP_List_Exchange
*)msg
);
3376 case MUIM_List_Insert
:
3377 return List__MUIM_Insert(cl
, obj
, (APTR
) msg
);
3378 case MUIM_List_InsertSingle
:
3379 return List__MUIM_InsertSingle(cl
, obj
, (APTR
) msg
);
3380 case MUIM_List_GetEntry
:
3381 return List__MUIM_GetEntry(cl
, obj
, (APTR
) msg
);
3382 case MUIM_List_Redraw
:
3383 return List__MUIM_Redraw(cl
, obj
, (APTR
) msg
);
3384 case MUIM_List_Remove
:
3385 return List__MUIM_Remove(cl
, obj
, (APTR
) msg
);
3386 case MUIM_List_Select
:
3387 return List__MUIM_Select(cl
, obj
, (APTR
) msg
);
3388 case MUIM_List_Construct
:
3389 return List__MUIM_Construct(cl
, obj
, (APTR
) msg
);
3390 case MUIM_List_Destruct
:
3391 return List__MUIM_Destruct(cl
, obj
, (APTR
) msg
);
3392 case MUIM_List_Compare
:
3393 return List__MUIM_Compare(cl
, obj
, (APTR
) msg
);
3394 case MUIM_List_Display
:
3395 return List__MUIM_Display(cl
, obj
, (APTR
) msg
);
3396 case MUIM_List_SelectChange
:
3397 return List__MUIM_SelectChange(cl
, obj
, (APTR
) msg
);
3398 case MUIM_List_CreateImage
:
3399 return List__MUIM_CreateImage(cl
, obj
, (APTR
) msg
);
3400 case MUIM_List_DeleteImage
:
3401 return List__MUIM_DeleteImage(cl
, obj
, (APTR
) msg
);
3402 case MUIM_List_Jump
:
3403 return List__MUIM_Jump(cl
, obj
, (APTR
) msg
);
3404 case MUIM_List_Move
:
3405 return List__MUIM_Move(cl
, obj
, (struct MUIP_List_Move
*)msg
);
3406 case MUIM_List_NextSelected
:
3407 return List__MUIM_NextSelected(cl
, obj
,
3408 (struct MUIP_List_NextSelected
*)msg
);
3409 case MUIM_List_TestPos
:
3410 return List__MUIM_TestPos(cl
, obj
, (APTR
) msg
);
3411 case MUIM_DragQuery
:
3412 return List__MUIM_DragQuery(cl
, obj
, (APTR
) msg
);
3413 case MUIM_DragFinish
:
3414 return List__MUIM_DragFinish(cl
, obj
, (APTR
) msg
);
3415 case MUIM_DragReport
:
3416 return List__MUIM_DragReport(cl
, obj
, (APTR
) msg
);
3418 return List__MUIM_DragDrop(cl
, obj
, (APTR
) msg
);
3419 case MUIM_CreateDragImage
:
3420 return List__MUIM_CreateDragImage(cl
, obj
, (APTR
) msg
);
3423 return DoSuperMethodA(cl
, obj
, msg
);
3425 BOOPSI_DISPATCHER_END
3430 const struct __MUIBuiltinClass _MUI_List_desc
=
3434 sizeof(struct MUI_ListData
),
3435 (void *) List_Dispatcher