Merging NList MCC 0.119 into the main branch.
[AROS.git] / workbench / classes / zune / nlist / nlistview_mcc / NListview.c
blob5c34075cfff9a6842b405b33b703efe725d1863e
1 /***************************************************************************
3 NListview.mcc - New Listview MUI Custom Class
4 Registered MUI class, Serial Number: 1d51 (0x9d510020 to 0x9d51002F)
6 Copyright (C) 1996-2001 by Gilles Masson
7 Copyright (C) 2001-2014 NList Open Source Team
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 NList classes Support Site: http://www.sf.net/projects/nlist-classes
21 $Id$
23 ***************************************************************************/
25 #include <string.h>
27 #include <clib/alib_protos.h>
28 #include <proto/muimaster.h>
29 #include <proto/intuition.h>
30 #include <proto/utility.h>
31 #include <proto/keymap.h>
33 #include "private.h"
34 #include "version.h"
36 #include "NListviews_mcp.h"
38 #include "muiextra.h"
40 #include "Debug.h"
42 #ifndef MUI_EHF_GUIMODE
43 #define MUI_EHF_GUIMODE (1<<1) /* set this if you dont want your handler to be called */
44 /* when your object is disabled or invisible */
45 #endif
47 static LONG IMsgToChar(struct IntuiMessage *imsg, ULONG dccode, ULONG dcquali)
49 struct InputEvent ie;
50 LONG key = -1;
52 ENTER();
54 memset(&ie, 0, sizeof(struct InputEvent));
55 ie.ie_Class = IECLASS_RAWKEY;
57 if(imsg->Class == IDCMP_RAWKEY)
59 TEXT buf[4];
61 ie.ie_Code = imsg->Code & ~dccode;
62 ie.ie_Qualifier = imsg->Qualifier & ~dcquali;
63 ie.ie_EventAddress = (APTR *)*((IPTR *)imsg->IAddress);
65 #if defined(__amigaos4__)
66 ie.ie_TimeStamp.Seconds = imsg->Seconds;
67 ie.ie_TimeStamp.Microseconds = imsg->Micros;
68 #else
69 ie.ie_TimeStamp.tv_secs = imsg->Seconds;
70 ie.ie_TimeStamp.tv_micro = imsg->Micros;
71 #endif
73 if(MapRawKey(&ie, buf , 3, 0) > 0)
74 key = (LONG)buf[0];
77 RETURN(key);
78 return key;
81 static IPTR mNLV_HandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
83 struct NLVData *data = INST_DATA(cl, obj);
84 struct IntuiMessage *imsg = msg->imsg;
85 IPTR result = 0;
87 ENTER();
89 if(data->LI_NList != NULL)
91 #if !defined(__amigaos4__) && !defined(__MORPHOS__) && !defined(__AROS__)
92 // with MUI 3.8 the embedded list object doesn't get this method,
93 // hence we must forward it ourself.
94 if(MUIMasterBase != NULL && MUIMasterBase->lib_Version <= 19 && msg->muikey != MUIKEY_NONE)
96 result = DoMethodA(data->LI_NList, (Msg)msg);
98 #endif
99 if(imsg != NULL)
101 switch(imsg->Class)
103 case IDCMP_RAWKEY:
105 if(data->ControlChar != '\0' && IMsgToChar(imsg, 0, (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) == data->ControlChar)
107 set(data->LI_NList, MUIA_NList_Active, imsg->Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? MUIV_NList_Active_Up: MUIV_NList_Active_Down);
110 break;
115 RETURN(result);
116 return result;
119 static IPTR mNLV_HandleInput(struct IClass *cl, Object *obj, struct MUIP_HandleInput *msg)
121 struct NLVData *data = INST_DATA(cl, obj);
122 IPTR result = 0;
124 ENTER();
126 if(data->LI_NList != NULL && msg->muikey != MUIKEY_NONE)
127 result = DoMethodA(data->LI_NList, (Msg)msg);
128 else
129 result = DoSuperMethodA(cl, obj, (Msg)msg);
131 RETURN(result);
132 return result;
135 static void AddVerticalScroller(Object *obj, struct NLVData *data)
137 ENTER();
139 if(data->Vert_Attached == FALSE)
141 ULONG entries;
142 ULONG visible;
143 ULONG first;
144 ULONG deltaFactor;
146 D(DBF_STARTUP, "adding vertical scrollbar");
148 // restore the list's current disabled state, because the scrollbar might
149 // have been removed in disabled state and the list has been reactivated
150 // in the meantime
151 set(data->PR_Vert, MUIA_Disabled, xget(data->LI_NList, MUIA_Disabled));
152 DoMethod(obj, OM_ADDMEMBER, data->PR_Vert);
154 // add notifications
155 DoMethod(data->LI_NList, MUIM_Notify, MUIA_NList_Prop_Entries, MUIV_EveryTime, data->PR_Vert, 3, MUIM_NoNotifySet, MUIA_Prop_Entries, MUIV_TriggerValue);
156 DoMethod(data->LI_NList, MUIM_Notify, MUIA_NList_Prop_Visible, MUIV_EveryTime, data->PR_Vert, 3, MUIM_NoNotifySet, MUIA_Prop_Visible, MUIV_TriggerValue);
157 DoMethod(data->LI_NList, MUIM_Notify, MUIA_NList_Prop_First, MUIV_EveryTime, data->PR_Vert, 3, MUIM_NoNotifySet, MUIA_Prop_First, MUIV_TriggerValue);
158 DoMethod(data->PR_Vert, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, data->LI_NList, 3, MUIM_NoNotifySet, MUIA_NList_Prop_First, MUIV_TriggerValue);
159 DoMethod(data->LI_NList, MUIM_Notify, MUIA_NList_VertDeltaFactor, MUIV_EveryTime, data->PR_Vert, 3, MUIM_NoNotifySet, MUIA_Prop_DeltaFactor, MUIV_TriggerValue);
161 // Get and set the attributes we just have installed the notifications for to
162 // immediately trigger them. Otherwise hiding and showing again the scrollbar
163 // while the number of entries changed in the meantime will result in wrong
164 // scrollbar dimensions (i.e. when switching folders in YAM).
165 entries = xget(data->LI_NList, MUIA_NList_Prop_Entries);
166 visible = xget(data->LI_NList, MUIA_NList_Prop_Visible);
167 first = xget(data->LI_NList, MUIA_NList_Prop_First);
168 deltaFactor = xget(data->LI_NList, MUIA_NList_VertDeltaFactor);
169 SetAttrs(data->LI_NList,
170 MUIA_NList_Prop_Entries, entries,
171 MUIA_NList_Prop_Visible, visible,
172 MUIA_NList_Prop_First, first,
173 MUIA_NList_VertDeltaFactor, deltaFactor,
174 TAG_DONE);
176 data->Vert_Attached = TRUE;
178 D(DBF_STARTUP, "vertical scrollbar added");
181 LEAVE();
184 static void RemoveVerticalScroller(Object *obj, struct NLVData *data)
186 ENTER();
188 if(data->Vert_Attached == TRUE)
190 D(DBF_STARTUP, "removing vertical scrollbar");
192 // remove notifications
193 DoMethod(data->LI_NList, MUIM_KillNotifyObj, MUIA_NList_Prop_Entries, data->PR_Vert);
194 DoMethod(data->LI_NList, MUIM_KillNotifyObj, MUIA_NList_Prop_Visible, data->PR_Vert);
195 DoMethod(data->LI_NList, MUIM_KillNotifyObj, MUIA_NList_Prop_First, data->PR_Vert);
196 DoMethod(data->PR_Vert, MUIM_KillNotifyObj, MUIA_Prop_First, data->LI_NList);
197 DoMethod(data->LI_NList, MUIM_KillNotifyObj, MUIA_NList_VertDeltaFactor, data->PR_Vert);
199 DoMethod(obj, OM_REMMEMBER, data->PR_Vert);
201 data->Vert_Attached = FALSE;
203 D(DBF_STARTUP, "vertical scrollbar removed");
206 LEAVE();
209 static void AddHorizontalScroller(Object *obj, struct NLVData *data)
211 ENTER();
213 if(data->Horiz_Attached == FALSE)
215 ULONG active;
216 ULONG entries;
217 ULONG visible;
218 ULONG first;
219 ULONG deltaFactor;
221 D(DBF_STARTUP, "adding horizontal scrollbar");
223 // restore the list's current disabled state, because the scrollbar might
224 // have been removed in disabled state and the list has been reactivated
225 // in the meantime
226 set(data->PR_Horiz, MUIA_Disabled, xget(data->LI_NList, MUIA_Disabled));
227 DoMethod(obj, OM_ADDMEMBER, data->PR_Horiz);
229 // add notifications
230 DoMethod(data->LI_NList, MUIM_Notify, MUIA_NList_Horiz_Entries, MUIV_EveryTime, data->PR_Horiz, 3, MUIM_NoNotifySet, MUIA_Prop_Entries, MUIV_TriggerValue);
231 DoMethod(data->LI_NList, MUIM_Notify, MUIA_NList_Horiz_Visible, MUIV_EveryTime, data->PR_Horiz, 3, MUIM_NoNotifySet, MUIA_Prop_Visible, MUIV_TriggerValue);
232 DoMethod(data->LI_NList, MUIM_Notify, MUIA_NList_Horiz_First, MUIV_EveryTime, data->PR_Horiz, 3, MUIM_NoNotifySet, MUIA_Prop_First, MUIV_TriggerValue);
233 DoMethod(data->PR_Horiz, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime, data->LI_NList, 3, MUIM_NoNotifySet, MUIA_NList_Horiz_First, MUIV_TriggerValue);
234 DoMethod(data->LI_NList, MUIM_Notify, MUIA_NList_HorizDeltaFactor, MUIV_EveryTime, data->PR_Horiz, 3, MUIM_NoNotifySet, MUIA_Prop_DeltaFactor, MUIV_TriggerValue);
236 // Get and set the attributes we just have installed the notifications for to
237 // immediately trigger them. Otherwise hiding and showing again the scrollbar
238 // while the number of entries changed in the meantime will result in wrong
239 // scrollbar dimensions (i.e. when switching folders in YAM).
240 active = xget(data->LI_NList, MUIA_NList_Active);
241 entries = xget(data->LI_NList, MUIA_NList_Horiz_Entries);
242 visible = xget(data->LI_NList, MUIA_NList_Horiz_Visible);
243 first = xget(data->LI_NList, MUIA_NList_Horiz_First);
244 deltaFactor = xget(data->LI_NList, MUIA_NList_HorizDeltaFactor);
245 SetAttrs(data->LI_NList,
246 MUIA_NList_Horiz_Entries, entries,
247 MUIA_NList_Horiz_Visible, visible,
248 MUIA_NList_Horiz_First, first,
249 MUIA_NList_HorizDeltaFactor, deltaFactor,
250 TAG_DONE);
252 // make sure the active entry is still visible after adding the scrollbar
253 // since the scrollbar is added at the bottom we only have to check for the
254 // last visible item
255 entries = xget(data->LI_NList, MUIA_NList_Entries);
256 visible = xget(data->LI_NList, MUIA_NList_Visible);
257 first = xget(data->LI_NList, MUIA_NList_First);
258 if(active == first+visible-1)
260 // the method must be pushed because we are currently inside a InitChange/ExitChange pair
261 // and the final height of the list cannot yet be determined correctly
262 // Additionally we must have completed the MUIM_Setup method to have a valid application pointer
263 if(data->SETUP == TRUE)
264 DoMethod(_app(obj), MUIM_Application_PushMethod, data->LI_NList, 2, MUIM_NList_Jump, active);
267 data->Horiz_Attached = TRUE;
269 D(DBF_STARTUP, "horizontal scrollbar added");
272 LEAVE();
275 static void RemoveHorizontalScroller(Object *obj, struct NLVData *data)
277 ENTER();
279 if(data->Horiz_Attached == TRUE)
281 D(DBF_STARTUP, "removing horizontal scrollbar");
283 // remove notifications
284 DoMethod(data->LI_NList, MUIM_KillNotifyObj, MUIA_NList_Horiz_Entries, data->PR_Horiz);
285 DoMethod(data->LI_NList, MUIM_KillNotifyObj, MUIA_NList_Horiz_Visible, data->PR_Horiz);
286 DoMethod(data->LI_NList, MUIM_KillNotifyObj, MUIA_NList_Horiz_First, data->PR_Horiz);
287 DoMethod(data->PR_Horiz, MUIM_KillNotifyObj, MUIA_Prop_First, data->LI_NList);
288 DoMethod(data->LI_NList, MUIM_KillNotifyObj, MUIA_NList_HorizDeltaFactor, data->PR_Horiz);
290 DoMethod(obj, OM_REMMEMBER, data->PR_Horiz);
292 data->Horiz_Attached = FALSE;
294 D(DBF_STARTUP, "horizontal scrollbar removed");
297 LEAVE();
300 static void NLV_Scrollers(Object *obj, struct NLVData *data, LONG vert, LONG horiz)
302 LONG scrollers = 0;
303 BOOL safeNotifies;
305 ENTER();
307 #if defined(__amigaos3__) || defined(__amigaos4__)
308 if(LIB_VERSION_IS_AT_LEAST(MUIMasterBase, 20, 5824))
310 // MUI4 for AmigaOS is safe for V20.5824+
311 safeNotifies = TRUE;
313 else if(LIB_VERSION_IS_AT_LEAST(MUIMasterBase, 20, 2346) && LIBREV(MUIMasterBase) < 5000)
315 // MUI3.9 for AmigaOS is safe for V20.2346+
316 safeNotifies = TRUE;
318 else
320 // MUI 3.8 and older version of MUI 3.9 or MUI4 are definitely unsafe
321 safeNotifies = FALSE;
323 #else
324 // MorphOS and AROS must be considered unsafe unless someone from the
325 // MorphOS/AROS team confirms that removing notifies in nested OM_SET
326 // calls is safe.
327 safeNotifies = FALSE;
328 #endif
330 if(vert & 0x0F)
332 data->Vert_ScrollBar = vert & 0x0F;
334 if(data->Vert_ScrollBar == MUIV_NListview_VSB_Default)
336 LONG *scrollbar;
338 if(DoMethod(obj, MUIM_GetConfigItem, MUICFG_NListview_VSB, (IPTR)&scrollbar))
339 data->VertSB = *scrollbar;
340 else
341 data->VertSB = MUIV_NListview_VSB_Always;
343 else
344 data->VertSB = data->Vert_ScrollBar;
346 // switch to always visible scrollbars if removing notifies is unsafe
347 if(safeNotifies == FALSE)
348 data->VertSB = MUIV_NListview_VSB_Always;
350 switch(data->VertSB)
352 case MUIV_NListview_VSB_Always:
353 case MUIV_NListview_VSB_Left:
355 scrollers |= MUIV_NListview_VSB_On;
357 break;
359 case MUIV_NListview_VSB_Auto:
360 case MUIV_NListview_VSB_FullAuto:
362 // nothing
364 break;
366 case MUIV_NListview_VSB_None:
368 scrollers |= MUIV_NListview_VSB_Off;
370 break;
374 if(horiz & 0x0F)
376 data->Horiz_ScrollBar = horiz & 0x0F;
378 if(data->Horiz_ScrollBar == MUIV_NListview_HSB_Default)
380 LONG *scrollbar;
382 if(DoMethod(obj, MUIM_GetConfigItem, MUICFG_NListview_HSB, (IPTR)&scrollbar))
383 data->HorizSB = *scrollbar;
384 else
385 data->HorizSB = DEFAULT_HSB;
387 else
388 data->HorizSB = data->Horiz_ScrollBar;
390 // switch to always visible scrollbars if removing notifies is unsafe
391 if(safeNotifies == FALSE)
392 data->HorizSB = MUIV_NListview_VSB_Always;
394 switch (data->HorizSB)
396 case MUIV_NListview_HSB_Always:
398 scrollers |= MUIV_NListview_HSB_On;
400 break;
402 case MUIV_NListview_HSB_Auto:
403 case MUIV_NListview_HSB_FullAuto:
405 // nothing
407 break;
409 case MUIV_NListview_HSB_None:
411 scrollers |= MUIV_NListview_HSB_Off;
413 break;
417 scrollers |= ((vert | horiz) & (MUIV_NListview_VSB_On | MUIV_NListview_HSB_On));
419 if(((data->VertSB == MUIV_NListview_VSB_Auto || data->VertSB == MUIV_NListview_VSB_Always) && (scrollers & MUIV_NListview_VSB_On) == MUIV_NListview_VSB_Off) ||
420 (data->VertSB == MUIV_NListview_VSB_None && (scrollers & MUIV_NListview_VSB_On) == MUIV_NListview_VSB_On) ||
421 (data->Vert_Attached == TRUE && (scrollers & MUIV_NListview_VSB_On) == MUIV_NListview_VSB_On) ||
422 (data->Vert_Attached == FALSE && (scrollers & MUIV_NListview_VSB_On) == MUIV_NListview_VSB_Off))
424 scrollers &= ~MUIV_NListview_VSB_On;
427 if(((data->HorizSB == MUIV_NListview_HSB_Auto || data->HorizSB == MUIV_NListview_HSB_Always) && (scrollers & MUIV_NListview_HSB_On) == MUIV_NListview_HSB_Off) ||
428 (data->HorizSB == MUIV_NListview_HSB_None && (scrollers & MUIV_NListview_HSB_On) == MUIV_NListview_HSB_On) ||
429 (data->Horiz_Attached == TRUE && (scrollers & MUIV_NListview_HSB_On) == MUIV_NListview_HSB_On) ||
430 (data->Horiz_Attached == FALSE && (scrollers & MUIV_NListview_HSB_On) == MUIV_NListview_HSB_Off))
432 scrollers &= ~MUIV_NListview_HSB_On;
435 // Don't do the dirty work of adding/removing the scrollbars here directly,
436 // but delay this until the application is idle again. This is necessary,
437 // because the OM_SET method calling this function can be called from within
438 // an OM_SET method of our group object. Removing any scrollbar in this
439 // situation will cause an access to the just removed object (or better its
440 // Exec node structure) which has become invalid due to the removal.
441 // The AmigaOS4 debug kernel shows this very good, because an access to the
442 // address 0xcccccccc happens which definitely proves the invalid access.
443 if(scrollers & (MUIV_NListview_VSB_On|MUIV_NListview_HSB_On))
445 // we must have completed the MUIM_Setup method to have a valid application pointer
446 if(data->SETUP == TRUE)
447 DoMethod(_app(obj), MUIM_Application_PushMethod, obj, 2, MUIM_NListview_SetScrollers, scrollers);
450 LEAVE();
453 #if !defined(__MORPHOS__)
454 #ifdef __AROS__
455 static __attribute__ ((noinline)) Object * VARARGS68K DoSuperNew(struct IClass *cl, Object *obj, Tag tag1, ...)
457 AROS_SLOWSTACKTAGS_PRE_AS(tag1, Object *)
458 retval = (Object *)DoSuperMethod(cl, obj, OM_NEW, AROS_SLOWSTACKTAGS_ARG(tag1), NULL);
459 AROS_SLOWSTACKTAGS_POST
461 #else
462 static Object * VARARGS68K DoSuperNew(struct IClass *cl, Object *obj, ...)
464 Object *rc;
465 VA_LIST args;
467 ENTER();
469 VA_START(args, obj);
470 rc = (Object *)DoSuperMethod(cl, obj, OM_NEW, VA_ARG(args, ULONG), NULL);
471 VA_END(args);
473 RETURN(rc);
474 return rc;
476 #endif
477 #endif // !__MORPHOS__
479 /* static ULONG mNLV_New(struct IClass *cl,Object *obj,Msg msg) */
480 static IPTR mNLV_New(struct IClass *cl, Object *obj, struct opSet *msg)
482 struct NLVData *data;
483 struct TagItem *tag;
484 Object *nlist = NULL;
485 Object *vgroup = NULL;
486 BOOL cyclechain = FALSE;
487 BOOL dropable = FALSE;
489 ENTER();
491 if((tag = FindTagItem(MUIA_Draggable, msg->ops_AttrList)) != NULL)
492 tag->ti_Tag = TAG_IGNORE;
494 if((tag = FindTagItem(MUIA_Dropable, msg->ops_AttrList)) != NULL)
496 tag->ti_Tag = TAG_IGNORE;
497 dropable = tag->ti_Data;
500 if((tag = FindTagItem(MUIA_CycleChain, msg->ops_AttrList)) != NULL)
502 tag->ti_Tag = TAG_IGNORE;
503 cyclechain = tag->ti_Data;
506 if((tag = FindTagItem(MUIA_NListview_NList, msg->ops_AttrList)) != NULL ||
507 (tag = FindTagItem(MUIA_Listview_List, msg->ops_AttrList)) != NULL)
509 nlist = (Object *) tag->ti_Data;
511 if(nlist != NULL)
513 if(dropable)
515 nnset(nlist,MUIA_Dropable, dropable);
518 if((tag = FindTagItem(MUIA_NList_DragType, msg->ops_AttrList)) != NULL ||
519 (tag = FindTagItem(MUIA_Listview_DragType, msg->ops_AttrList)) != NULL)
521 nnset(nlist,tag->ti_Tag,tag->ti_Data);
524 if((tag = FindTagItem(MUIA_Listview_Input, msg->ops_AttrList)) != NULL ||
525 (tag = FindTagItem(MUIA_NList_Input, msg->ops_AttrList)) != NULL)
527 nnset(nlist,tag->ti_Tag,tag->ti_Data);
530 if((tag = FindTagItem(MUIA_Listview_MultiSelect, msg->ops_AttrList)) != NULL ||
531 (tag = FindTagItem(MUIA_NList_MultiSelect, msg->ops_AttrList)) != NULL)
533 nnset(nlist,tag->ti_Tag,tag->ti_Data);
536 if((tag = FindTagItem(MUIA_Listview_DoubleClick, msg->ops_AttrList)) != NULL ||
537 (tag = FindTagItem(MUIA_NList_DoubleClick, msg->ops_AttrList)) != NULL)
539 nnset(nlist,tag->ti_Tag,tag->ti_Data);
542 if((tag = FindTagItem(MUIA_Listview_DefClickColumn, msg->ops_AttrList)) != NULL ||
543 (tag = FindTagItem(MUIA_NList_DefClickColumn, msg->ops_AttrList)) != NULL)
545 nnset(nlist,tag->ti_Tag,tag->ti_Data);
548 else
550 obj = NULL;
551 RETURN(obj);
552 return((IPTR)obj);
555 else
557 nlist = MUI_NewObject(MUIC_NList, MUIA_Dropable, dropable, TAG_MORE, msg->ops_AttrList);
560 obj = (Object *)DoSuperNew(cl, obj,
561 MUIA_Group_Horiz, TRUE,
562 MUIA_Group_Spacing, 0,
563 MUIA_CycleChain, cyclechain,
564 NoFrame,
565 Child, vgroup = VGroup,
566 MUIA_Group_Spacing, 0,
567 Child, nlist,
568 TAG_DONE),
569 TAG_MORE, msg->ops_AttrList
572 if(obj)
574 data = INST_DATA(cl,obj);
575 data->sem = FALSE;
576 data->SETUP = FALSE;
577 data->LI_NList = nlist;
578 data->Group = vgroup;
579 data->Vert_Attached = FALSE;
580 data->Horiz_Attached = FALSE;
581 data->Vert_ScrollBar = MUIV_NListview_VSB_Default;
582 data->Horiz_ScrollBar = MUIV_NListview_HSB_Default;
583 if((tag = FindTagItem(MUIA_Listview_ScrollerPos, msg->ops_AttrList)) != NULL)
585 if(tag->ti_Data == MUIV_Listview_ScrollerPos_None)
587 data->Vert_ScrollBar = MUIV_NListview_VSB_None;
588 data->Horiz_ScrollBar = MUIV_NListview_HSB_None;
590 else if(tag->ti_Data == MUIV_Listview_ScrollerPos_Left)
592 data->Vert_ScrollBar = MUIV_NListview_VSB_Left;
594 else if(tag->ti_Data == MUIV_Listview_ScrollerPos_Right)
596 data->Vert_ScrollBar = MUIV_NListview_VSB_Always;
600 if((tag = FindTagItem(MUIA_NListview_Vert_ScrollBar, msg->ops_AttrList)) != NULL)
601 data->Vert_ScrollBar = tag->ti_Data;
603 if((tag = FindTagItem(MUIA_NListview_Horiz_ScrollBar, msg->ops_AttrList)) != NULL)
604 data->Horiz_ScrollBar = tag->ti_Data;
606 if((tag = FindTagItem(MUIA_ControlChar, msg->ops_AttrList)) != NULL)
607 data->ControlChar = tag->ti_Data;
609 data->VertSB = data->Vert_ScrollBar;
610 data->HorizSB = data->Horiz_ScrollBar;
612 // create the two scrollbar objects
613 data->PR_Vert = ScrollbarObject,
614 MUIA_Group_Horiz, FALSE,
615 End;
617 data->PR_Horiz = ScrollbarObject,
618 MUIA_Group_Horiz, TRUE,
619 End;
621 DoMethod(data->LI_NList, MUIM_Notify, MUIA_NListview_Horiz_ScrollBar, MUIV_EveryTime, obj, 3, MUIM_Set, MUIA_NListview_Horiz_ScrollBar, MUIV_TriggerValue);
623 set(data->LI_NList, MUIA_NList_KeepActive, (IPTR)obj);
625 // derive the "active border visible" setting from the embedded list
626 if(xget(data->LI_NList, MUIA_NList_ActiveObjectOnClick) == TRUE)
627 _flags(obj) |= (1<<7);
630 RETURN(obj);
631 return((IPTR)obj);
635 static IPTR mNLV_Dispose(struct IClass *cl,Object *obj,Msg msg)
637 struct NLVData *data = INST_DATA(cl, obj);
639 ENTER();
641 // dispose the scrollbars if they are not currently part of the layout
642 if(data->PR_Vert != NULL && data->Vert_Attached == FALSE)
644 MUI_DisposeObject(data->PR_Vert);
645 data->PR_Vert = NULL;
647 if(data->PR_Horiz != NULL && data->Horiz_Attached == FALSE)
649 MUI_DisposeObject(data->PR_Horiz);
650 data->PR_Horiz = NULL;
653 LEAVE();
654 return DoSuperMethodA(cl,obj,msg);
657 static IPTR mNLV_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
659 struct NLVData *data = INST_DATA(cl, obj);
660 IPTR result = FALSE;
662 ENTER();
664 data->SETUP = FALSE;
666 if(data->sem == FALSE)
668 data->sem = TRUE;
669 NLV_Scrollers(obj, data, data->Vert_ScrollBar, data->Horiz_ScrollBar);
670 data->sem = FALSE;
673 // Add the event handler for RAWKEY now
674 data->eh.ehn_Class = cl;
675 data->eh.ehn_Object = obj;
676 data->eh.ehn_Events = IDCMP_RAWKEY;
677 data->eh.ehn_Flags = MUI_EHF_GUIMODE;
678 data->eh.ehn_Priority = -1;
679 if(_win(obj) != NULL)
680 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->eh);
682 if(DoSuperMethodA(cl, obj, (Msg)msg))
684 result = TRUE;
685 data->SETUP = TRUE;
688 RETURN(result);
689 return result;
693 static IPTR mNLV_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
695 struct NLVData *data = INST_DATA(cl, obj);
697 ENTER();
699 if(_win(obj) != NULL)
700 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->eh);
702 data->SETUP = FALSE;
704 LEAVE();
705 return DoSuperMethodA(cl, obj, (Msg)msg);
709 static IPTR mNLV_Notify(struct IClass *cl, Object *obj, struct MUIP_Notify *msg)
711 struct NLVData *data = INST_DATA(cl, obj);
713 switch(msg->TrigAttr)
715 case MUIA_List_Prop_Entries:
716 case MUIA_List_Prop_Visible:
717 case MUIA_List_Prop_First:
718 case MUIA_NList_Horiz_Entries:
719 case MUIA_NList_Horiz_Visible:
720 case MUIA_NList_Horiz_First:
721 case MUIA_NList_HorizDeltaFactor:
722 case MUIA_NList_Prop_Entries:
723 case MUIA_NList_Prop_Visible:
724 case MUIA_NList_Prop_First:
725 case MUIA_NList_VertDeltaFactor:
726 case MUIA_NList_SelectChange:
727 case MUIA_NList_MultiClick:
728 case MUIA_NList_DoubleClick:
729 case MUIA_NList_EntryClick:
730 case MUIA_NList_Active:
731 case MUIA_NList_First:
732 case MUIA_NList_Entries:
733 case MUIA_NList_TitleClick:
734 case MUIA_List_Active:
735 case MUIA_Listview_SelectChange:
736 case MUIA_Listview_DoubleClick:
738 return DoMethodA(data->LI_NList, (Msg)msg);
741 default:
742 return DoSuperMethodA(cl, obj, (Msg)msg);
748 static IPTR mNLV_Set(struct IClass *cl,Object *obj,Msg msg)
750 struct NLVData *data = INST_DATA(cl, obj);
751 struct TagItem *tags, *tag;
753 ENTER();
755 tags = ((struct opSet *)msg)->ops_AttrList;
756 while((tag = NextTagItem((APTR)&tags)) != NULL)
758 switch (tag->ti_Tag)
760 case MUIA_Listview_ScrollerPos:
762 if(tag->ti_Data == MUIV_Listview_ScrollerPos_None)
763 tag->ti_Data = MUIV_NListview_VSB_None;
764 else if(tag->ti_Data == MUIV_Listview_ScrollerPos_Left)
765 tag->ti_Data = MUIV_NListview_VSB_Left;
766 else if(tag->ti_Data == MUIV_Listview_ScrollerPos_Right)
767 tag->ti_Data = MUIV_NListview_VSB_Always;
768 else
769 tag->ti_Data = MUIV_NListview_VSB_Default;
771 // fall through...
773 case MUIA_NListview_Vert_ScrollBar:
775 tag->ti_Tag = TAG_IGNORE;
776 if(data->sem == FALSE)
778 data->sem = TRUE;
779 NLV_Scrollers(obj, data, tag->ti_Data, 0);
780 data->sem = FALSE;
783 break;
785 case MUIA_NListview_Horiz_ScrollBar:
787 tag->ti_Tag = TAG_IGNORE;
788 if(data->sem == FALSE)
790 data->sem = TRUE;
791 NLV_Scrollers(obj, data, 0, tag->ti_Data);
792 data->sem = FALSE;
795 break;
797 case MUIA_NList_KeyUpFocus:
798 case MUIA_NList_KeyDownFocus:
799 case MUIA_NList_KeyLeftFocus:
800 case MUIA_NList_KeyRightFocus:
802 // forward these to the embedded list object
803 if(data->LI_NList != NULL)
804 set(data->LI_NList, tag->ti_Tag, tag->ti_Data);
806 break;
810 LEAVE();
811 return DoSuperMethodA(cl, obj, msg);
815 static IPTR mNLV_Get(struct IClass *cl,Object *obj,Msg msg)
817 struct NLVData *data = INST_DATA(cl, obj);
818 IPTR *store = ((struct opGet *)msg)->opg_Storage;
819 IPTR result = FALSE;
821 ENTER();
823 switch(((struct opGet *)msg)->opg_AttrID)
825 case MUIA_Listview_List:
826 case MUIA_NListview_NList:
828 *store = (IPTR)data->LI_NList;
829 result = TRUE;
831 break;
833 case MUIA_NListview_Vert_ScrollBar:
835 *store = (IPTR)data->VertSB;
836 result = TRUE;
838 break;
840 case MUIA_NListview_Horiz_ScrollBar:
842 *store = (IPTR)data->HorizSB;
843 result = TRUE;
845 break;
847 case MUIA_NListview_VSB_Width:
849 if(data->Vert_Attached == TRUE)
850 *store = (IPTR)_width(data->PR_Vert);
851 else
852 *store = (IPTR)0;
854 result = TRUE;
856 break;
858 case MUIA_NListview_HSB_Height:
860 if(data->Horiz_Attached == TRUE)
861 *store = (IPTR)_height(data->PR_Horiz);
862 else
863 *store = (IPTR)0;
865 result = TRUE;
867 break;
869 case MUIA_Version:
871 *store = LIB_VERSION;
872 result = TRUE;
874 break;
876 case MUIA_Revision:
878 *store = LIB_REVISION;
879 result = TRUE;
881 break;
883 default:
885 result = DoSuperMethodA(cl, obj, msg);
887 break;
890 RETURN(result);
891 return result;
894 static IPTR mNLV_GoActive(struct IClass *cl, Object *obj, Msg msg)
896 struct NLVData *data = INST_DATA(cl, obj);
898 // forward the method to the NList object
899 D(DBF_ALWAYS, "go active %08lx", obj);
900 if(data->LI_NList != NULL)
901 DoMethod(data->LI_NList, MUIM_NList_GoActive);
903 return DoSuperMethodA(cl, obj, msg);
906 static IPTR mNLV_GoInactive(struct IClass *cl, Object *obj, Msg msg)
908 struct NLVData *data = INST_DATA(cl, obj);
910 D(DBF_ALWAYS, "go inactive %08lx", obj);
911 // forward the method to the NList object
912 if(data->LI_NList != NULL)
913 DoMethod(data->LI_NList, MUIM_NList_GoInactive);
915 return DoSuperMethodA(cl, obj, msg);
918 static IPTR mNLV_SetScrollers(struct IClass *cl, Object *obj, struct MUIP_NListview_SetScrollers *msg)
920 struct NLVData *data = INST_DATA(cl, obj);
922 if(msg->scrollers & MUIV_NListview_VSB_On)
924 if(data->SETUP == FALSE || DoMethod(obj, MUIM_Group_InitChange))
926 if((msg->scrollers & MUIV_NListview_VSB_On) == MUIV_NListview_VSB_On)
928 AddVerticalScroller(obj, data);
929 if(data->VertSB == MUIV_NListview_VSB_Left)
930 DoMethod(obj, MUIM_Group_Sort, data->PR_Vert, data->Group, NULL);
932 else
934 RemoveVerticalScroller(obj, data);
937 if(msg->scrollers & MUIV_NListview_HSB_On)
939 if(data->SETUP == FALSE || DoMethod(data->Group, MUIM_Group_InitChange))
941 if((msg->scrollers & MUIV_NListview_HSB_On) == MUIV_NListview_HSB_On)
942 AddHorizontalScroller(data->Group, data);
943 else
944 RemoveHorizontalScroller(data->Group, data);
946 if(data->SETUP == TRUE)
947 DoMethod(data->Group, MUIM_Group_ExitChange);
951 if(data->SETUP == TRUE)
952 DoMethod(obj, MUIM_Group_ExitChange);
955 else if(msg->scrollers & MUIV_NListview_HSB_On)
957 if(data->SETUP == FALSE || DoMethod(data->Group, MUIM_Group_InitChange))
959 if((msg->scrollers & MUIV_NListview_HSB_On) == MUIV_NListview_HSB_On)
960 AddHorizontalScroller(data->Group, data);
961 else
962 RemoveHorizontalScroller(data->Group, data);
964 if(data->SETUP == TRUE)
965 DoMethod(data->Group, MUIM_Group_ExitChange);
969 return 0;
972 DISPATCHER(_Dispatcher)
974 switch(msg->MethodID)
976 case OM_NEW : return(mNLV_New(cl,obj,(APTR)msg));
977 case OM_DISPOSE : return(mNLV_Dispose(cl,obj,(APTR)msg));
978 case OM_GET : return(mNLV_Get(cl,obj,(APTR)msg));
979 case OM_SET : return(mNLV_Set(cl,obj,(APTR)msg));
980 case MUIM_Setup : return(mNLV_Setup(cl,obj,(APTR)msg));
981 case MUIM_Cleanup : return(mNLV_Cleanup(cl,obj,(APTR)msg));
982 case MUIM_HandleInput : return(mNLV_HandleInput(cl,obj,(APTR)msg));
983 case MUIM_HandleEvent : return(mNLV_HandleEvent(cl,obj,(APTR)msg));
984 case MUIM_NList_QueryBeginning : return(0);
985 case MUIM_DragQuery : return(MUIV_DragQuery_Refuse);
987 // we catch all notify relevant method
988 // calls in one function
989 case MUIM_KillNotify :
990 case MUIM_KillNotifyObj :
991 case MUIM_Notify : return (mNLV_Notify(cl,obj,(APTR)msg));
993 case MUIM_GoActive : return mNLV_GoActive(cl, obj, msg);
994 case MUIM_GoInactive : return mNLV_GoInactive(cl, obj, msg);
996 // the following method calls are all forwarded
997 // to the corresponding NList object
998 case MUIM_List_Sort :
999 case MUIM_List_Insert :
1000 case MUIM_List_InsertSingle :
1001 case MUIM_List_GetEntry :
1002 case MUIM_List_Clear :
1003 case MUIM_List_Jump :
1004 case MUIM_List_Select :
1005 case MUIM_List_TestPos :
1006 case MUIM_List_Redraw :
1007 case MUIM_List_Exchange :
1008 case MUIM_List_Move :
1009 case MUIM_List_NextSelected :
1010 case MUIM_List_Remove :
1011 case MUIM_List_CreateImage :
1012 case MUIM_List_DeleteImage :
1013 case MUIM_NList_Sort :
1014 case MUIM_NList_Sort2 :
1015 case MUIM_NList_Insert :
1016 case MUIM_NList_InsertSingle :
1017 case MUIM_NList_GetEntry :
1018 case MUIM_NList_Clear :
1019 case MUIM_NList_Jump :
1020 case MUIM_NList_Select :
1021 case MUIM_NList_TestPos :
1022 case MUIM_NList_Redraw :
1023 case MUIM_NList_RedrawEntry :
1024 case MUIM_NList_Exchange :
1025 case MUIM_NList_Move :
1026 case MUIM_NList_NextSelected :
1027 case MUIM_NList_Remove :
1028 case MUIM_NList_CreateImage :
1029 case MUIM_NList_DeleteImage :
1030 case MUIM_NList_CopyToClip :
1031 case MUIM_NList_UseImage :
1032 case MUIM_NList_ReplaceSingle :
1033 case MUIM_NList_InsertWrap :
1034 case MUIM_NList_InsertSingleWrap:
1035 case MUIM_NList_GetEntryInfo :
1036 case MUIM_NList_GetSelectInfo :
1037 case MUIM_NList_CopyTo :
1038 case MUIM_NList_DropType :
1039 case MUIM_NList_DropDraw :
1040 case MUIM_NList_DoMethod :
1041 case MUIM_NList_ColWidth :
1042 case MUIM_NList_ColToColumn :
1043 case MUIM_NList_ColumnToCol :
1045 struct NLVData *data = INST_DATA(cl, obj);
1047 if(data->LI_NList != NULL)
1048 return DoMethodA(data->LI_NList, msg);
1049 else
1050 return 0;
1053 case MUIM_NListview_SetScrollers: return mNLV_SetScrollers(cl, obj, (APTR)msg);
1055 default: return DoSuperMethodA(cl, obj, msg);