make sure labelSplit_RemainingCharsAfterSplit is not used uninitialized. (NicJA)
[AROS.git] / workbench / system / Wanderer / Classes / iconlist.c
blobd62f7c8dfdd9b1f78332e7dc8e016e71a8af0708
1 /*
2 Copyright © 2001-2019, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "../portable_macros.h"
7 #if !defined(__AROS__)
8 #define WANDERER_BUILTIN_ICONLIST 1
9 #else
10 #define DEBUG 0
11 #include <aros/debug.h>
12 #endif
14 //#define DEBUG_ILC_FUNCS
15 //#define DEBUG_ILC_ATTRIBS
16 //#define DEBUG_ILC_EVENTS
17 //#define DEBUG_ILC_KEYEVENTS
18 //#define DEBUG_ILC_ICONDRAGDROP
19 //#define DEBUG_ILC_ICONRENDERING
20 //#define DEBUG_ILC_ICONSORTING
21 //#define DEBUG_ILC_ICONSORTING_DUMP
22 //#define DEBUG_ILC_ICONPOSITIONING
23 //#define DEBUG_ILC_LASSO
24 //#define DEBUG_ILC_MEMALLOC
26 #define CREATE_FULL_DRAGIMAGE
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <math.h>
34 #include <dos/dos.h>
35 #include <dos/datetime.h>
36 #include <dos/filehandler.h>
38 #include <exec/memory.h>
39 #include <exec/rawfmt.h>
40 #include <graphics/gfx.h>
41 #include <graphics/view.h>
42 #include <graphics/rpattr.h>
43 #include <workbench/icon.h>
44 #include <workbench/workbench.h>
46 #if defined(__AROS__)
47 #include <devices/rawkeycodes.h>
48 #include <clib/alib_protos.h>
49 #else
50 #include <devices_AROS/rawkeycodes.h>
51 #endif
54 #include <proto/exec.h>
55 #include <proto/graphics.h>
56 #include <proto/utility.h>
57 #include <proto/dos.h>
58 #include <proto/icon.h>
59 #include <proto/layers.h>
60 #include <proto/dos.h>
61 #include <proto/iffparse.h>
63 #if defined(__AROS__)
64 #include <prefs/prefhdr.h>
65 #include <prefs/wanderer.h>
66 #else
67 #include <prefs_AROS/prefhdr.h>
68 #include <prefs_AROS/wanderer.h>
69 #endif
71 #include <proto/cybergraphics.h>
73 #if defined(__AROS__)
74 #include <cybergraphx/cybergraphics.h>
75 #else
76 #include <cybergraphx_AROS/cybergraphics.h>
77 #endif
80 #if defined(__AMIGA__) && !defined(__PPC__)
81 #define NO_INLINE_STDARG
82 #endif
83 #include <proto/intuition.h>
84 #include <proto/muimaster.h>
85 #include <libraries/mui.h>
86 #include "iconlist_attributes.h"
87 #include "icon_attributes.h"
88 #include "iconlist.h"
89 #include "iconlist_private.h"
90 #include "iconlistview.h"
92 #if !defined(__AROS__)
93 #define DEBUG 1
95 #ifdef DEBUG
96 #define D(x) if (DEBUG) x
97 #ifdef __amigaos4__
98 #define bug DebugPrintF
99 #else
100 #define bug kprintf
101 #endif
102 #else
103 #define D(...)
104 #endif
105 #endif
107 #define _between(a,x,b) ((x)>=(a) && (x)<=(b))
108 #define _isinobject(x,y) (_between(_mleft(obj),(x),_mright (obj)) \
109 && _between(_mtop(obj) ,(y),_mbottom(obj)))
111 extern struct Library *MUIMasterBase;
113 static struct Hook __iconlist_UpdateLabels_hook;
115 // N.B: We Handle frame/background rendering so make sure icon.library doesnt do it ..
116 static struct TagItem __iconList_DrawIconStateTags[] = {
117 { ICONDRAWA_Frameless, TRUE },
118 { ICONDRAWA_Borderless, TRUE },
119 { ICONDRAWA_EraseBackground, FALSE },
120 { TAG_DONE, }
123 #if 0
124 static struct TagItem __iconList_BackBuffLayerTags[] =
126 { LA_Visible, FALSE },
127 { TAG_DONE, }
129 #endif
131 #ifndef NO_ICON_POSITION
132 #define NO_ICON_POSITION (0x8000000) /* belongs to workbench/workbench.h */
133 #endif
135 #define UPDATE_HEADERENTRY 1
136 #define UPDATE_SINGLEENTRY 2
137 #define UPDATE_SCROLL 3
138 #define UPDATE_RESIZE 4
140 #define LEFT_BUTTON 1
141 #define RIGHT_BUTTON 2
142 #define MIDDLE_BUTTON 4
144 #define ICONLIST_DRAWMODE_NORMAL 1
145 #define ICONLIST_DRAWMODE_FAST 2
147 /* Values used for List View-Mode */
148 #define COLOR_COLUMN_BACKGROUND 0
149 #define COLOR_COLUMN_BACKGROUND_SORTED 1
150 #define COLOR_COLUMN_BACKGROUND_LASSO 2
151 #define COLOR_COLUMN_BACKGROUND_LASSO_SORTED 3
153 #define COLOR_SELECTED_BACKGROUND 4
154 #define COLOR_SELECTED_BACKGROUND_SORTED 5
156 #define MIN_COLUMN_WIDTH 10
158 #define COLUMN_ALIGN_LEFT 0
159 #define COLUMN_ALIGN_CENTER 1
160 #define COLUMN_ALIGN_RIGHT 2
162 #define LINE_SPACING_TOP 2
163 #define LINE_SPACING_BOTTOM 2
164 #define LINE_EXTRAHEIGHT (LINE_SPACING_TOP + LINE_SPACING_BOTTOM)
166 #define LINE_SPACING_LEFT 1
167 #define LINE_SPACING_RIGHT 1
168 #define LINE_EXTRAWIDTH (LINE_SPACING_LEFT + LINE_SPACING_RIGHT)
170 #define ENTRY_SPACING_LEFT 1
171 #define ENTRY_SPACING_RIGHT 1
172 #define ENTRY_EXTRAWIDTH (ENTRY_SPACING_LEFT + ENTRY_SPACING_RIGHT)
174 #define HEADERLINE_SPACING_TOP 3
175 #define HEADERLINE_SPACING_BOTTOM 3
176 #define HEADERLINE_EXTRAHEIGHT (HEADERLINE_SPACING_TOP + HEADERLINE_SPACING_BOTTOM)
178 #define HEADERLINE_SPACING_LEFT 1
179 #define HEADERLINE_SPACING_RIGHT 1
180 #define HEADERLINE_EXTRAWIDTH (HEADERLINE_SPACING_LEFT + HEADERLINE_SPACING_RIGHT)
182 #define HEADERENTRY_SPACING_LEFT 4
183 #define HEADERENTRY_SPACING_RIGHT 4
184 #define HEADERENTRY_EXTRAWIDTH (HEADERENTRY_SPACING_LEFT + HEADERENTRY_SPACING_RIGHT)
186 enum
188 INDEX_TYPE,
189 INDEX_NAME,
190 INDEX_SIZE,
191 INDEX_PROTECTION,
192 INDEX_LASTACCESS,
193 INDEX_COMMENT
196 /**************************************************************************
197 Support Functions
198 **************************************************************************/
200 #define ForeachPrevNode(list, node) \
201 for \
203 node = (void *)(((struct List *)(list))->lh_TailPred); \
204 ((struct Node *)(node))->ln_Pred; \
205 node = (void *)(((struct Node *)(node))->ln_Pred) \
208 #define RPALPHAFLAT (1 << 0)
209 #define RPALPHARADIAL (1 << 1)
211 static void RastPortSetAlpha(struct RastPort *arport, ULONG ax, ULONG ay, ULONG width, ULONG height, UBYTE val, UBYTE alphamode)
213 ULONG x, y;
214 ULONG alphaval, pixelval;
215 APTR buffer, pixelptr;
217 if ((buffer = AllocVec(width * height * sizeof(ULONG), MEMF_ANY)) == NULL)
218 return;
220 ReadPixelArray(buffer, 0, 0, width * sizeof(ULONG), arport, 0, 0, width, height, RECTFMT_ARGB);
222 pixelptr = buffer;
224 for (y = 0; y < height; y++)
226 for (x = 0; x < width; x++)
228 if((pixelval = *((ULONG *)pixelptr)))
230 if (alphamode == RPALPHARADIAL){
231 //Set the alpha value based on distance from ax,ay
232 } else {
233 alphaval = val;
235 pixelval = (pixelval & 0xffffff00) | alphaval;
236 *((ULONG *)pixelptr) = pixelval;
238 pixelptr += sizeof(ULONG);
242 WritePixelArray(buffer, 0, 0, width * sizeof(ULONG), arport, 0, 0, width, height, RECTFMT_ARGB);
243 FreeVec(buffer);
246 ///RectAndRect()
247 // Entry/Label Area support functions
248 static int RectAndRect(struct Rectangle *a, struct Rectangle *b)
250 if ((a->MinX > b->MaxX) || (a->MinY > b->MaxY) || (a->MaxX < b->MinX) || (a->MaxY < b->MinY))
251 return 0;
252 return 1;
256 ///RegionAndRect()
258 * offx and offy define the largest jump from b->MinX b->MinY that is safe not to
259 * miss a free zone of size b
261 static int RegionAndRect(struct Region * a, struct Rectangle *b, LONG *offx, LONG *offy)
263 D(bug("Region (%d, %d)(%d, %d), Rect (%d, %d)(%d, %d)\n",
264 (LONG)a->bounds.MinX, (LONG)a->bounds.MinY, (LONG)a->bounds.MaxX, (LONG)a->bounds.MaxY,
265 (LONG)b->MinX, (LONG)b->MinY, (LONG)b->MaxX, (LONG)b->MaxY));
267 /* First check with region bounds */
268 if (RectAndRect(&a->bounds, b) == 0)
269 return 0;
271 if (a->RegionRectangle)
273 struct RegionRectangle * c = a->RegionRectangle;
274 while(c)
276 struct Rectangle d = {
277 a->bounds.MinX + c->bounds.MinX,
278 a->bounds.MinY + c->bounds.MinY,
279 a->bounds.MinX + c->bounds.MaxX,
280 a->bounds.MinY + c->bounds.MaxY
281 }; /* We need absolute coordinates */
282 struct Rectangle intersect;
284 if (AndRectRect(&d, b, &intersect))
286 *offx = (LONG)(intersect.MaxX - intersect.MinX + 1);
287 *offy = (LONG)(intersect.MaxY - intersect.MinY + 1);
288 return 1;
290 c = c->Next;
294 return 0;
297 ///Node_NextVisible()
298 // IconEntry List navigation functions ..
299 static struct IconEntry *Node_NextVisible(struct IconEntry *current_Node)
301 current_Node = (struct IconEntry *)GetSucc(&current_Node->ie_IconNode);
302 while ((current_Node != NULL) && (!(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
304 current_Node = (struct IconEntry *)GetSucc(&current_Node->ie_IconNode);
306 return current_Node;
310 ///Node_FirstVisible()
311 static struct IconEntry *Node_FirstVisible(struct List *icon_list)
313 struct IconEntry *current_Node = (struct IconEntry *)GetHead(icon_list);
315 if ((current_Node != NULL) && !(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE))
316 current_Node = Node_NextVisible(current_Node);
318 return current_Node;
322 ///Node_PreviousVisible()
323 static struct IconEntry *Node_PreviousVisible(struct IconEntry *current_Node)
325 current_Node = (struct IconEntry *)GetPred(&current_Node->ie_IconNode);
326 while ((current_Node != NULL) && (!(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
328 current_Node = (struct IconEntry *)GetPred(&current_Node->ie_IconNode);
330 return current_Node;
334 ///Node_LastVisible()
335 static struct IconEntry *Node_LastVisible(struct List *icon_list)
337 struct IconEntry *current_Node = (struct IconEntry *)GetTail(icon_list);
339 if ((current_Node != NULL) && !(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE))
340 current_Node = Node_PreviousVisible(current_Node);
342 return current_Node;
346 const UBYTE MSG_MEM_G[] = "GB";
347 const UBYTE MSG_MEM_M[] = "MB";
348 const UBYTE MSG_MEM_K[] = "KB";
349 const UBYTE MSG_MEM_B[] = "Bytes";
351 ///FmtSizeToString()
352 static void FmtSizeToString(UBYTE *buf, ULONG num)
354 UQUAD d;
355 const UBYTE *ch;
356 struct
358 ULONG val;
359 ULONG dec;
360 } array =
362 num,
366 if (num >= 1073741824)
368 //Gigabytes
369 array.val = num >> 30;
370 d = ((UQUAD)num * 10 + 536870912) / 1073741824;
371 array.dec = d % 10;
372 ch = MSG_MEM_G;
374 else if (num >= 1048576)
376 //Megabytes
377 array.val = num >> 20;
378 d = ((UQUAD)num * 10 + 524288) / 1048576;
379 array.dec = d % 10;
380 ch = MSG_MEM_M;
382 else if (num >= 1024)
384 //Kilobytes
385 array.val = num >> 10;
386 d = (num * 10 + 512) / 1024;
387 array.dec = d % 10;
388 ch = MSG_MEM_K;
390 else
392 //Bytes
393 array.val = num;
394 array.dec = 0;
395 d = 0;
396 ch = MSG_MEM_B;
399 if (!array.dec && (d > array.val * 10))
401 array.val++;
404 RawDoFmt(array.dec ? "%lu.%lu" : "%lu", (RAWARG)&array, RAWFMTFUNC_STRING, buf);
406 while (*buf)
408 buf++;
411 sprintf(buf, " %s", ch);
415 ///GetAbsoluteLassoRect()
416 // get positive lasso coords
417 static void GetAbsoluteLassoRect(struct IconList_DATA *data, struct Rectangle *LassoRectangle)
419 WORD minx = data->icld_LassoRectangle.MinX;
420 WORD miny = data->icld_LassoRectangle.MinY;
421 WORD maxx = data->icld_LassoRectangle.MaxX;
422 WORD maxy = data->icld_LassoRectangle.MaxY;
424 #if defined(DEBUG_ILC_LASSO) || defined(DEBUG_ILC_FUNCS)
425 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
426 #endif
428 if (minx > maxx)
430 /* Swap minx, maxx */
431 minx ^= maxx;
432 maxx ^= minx;
433 minx ^= maxx;
436 if (miny > maxy)
438 /* Swap miny, maxy */
439 miny ^= maxy;
440 maxy ^= miny;
441 miny ^= maxy;
444 LassoRectangle->MinX = data->view_rect.MinX - data->icld_ViewX + minx;
445 LassoRectangle->MinY = data->view_rect.MinY - data->icld_ViewY + miny;
446 LassoRectangle->MaxX = data->view_rect.MinX - data->icld_ViewX + maxx;
447 LassoRectangle->MaxY = data->view_rect.MinY - data->icld_ViewY + maxy;
451 ///IconList_InvertPixelRect()
452 static void IconList_InvertPixelRect(struct RastPort *rp, WORD minx, WORD miny, WORD maxx, WORD maxy, struct Rectangle *clip)
454 struct Rectangle r, clipped_r;
456 #if defined(DEBUG_ILC_RENDERING) || defined(DEBUG_ILC_FUNCS)
457 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
458 #endif
460 if (maxx < minx)
462 /* Swap minx, maxx */
463 minx ^= maxx;
464 maxx ^= minx;
465 minx ^= maxx;
468 if (maxy < miny)
470 /* Swap miny, maxy */
471 miny ^= maxy;
472 maxy ^= miny;
473 miny ^= maxy;
476 r.MinX = minx;
477 r.MinY = miny;
478 r.MaxX = maxx;
479 r.MaxY = maxy;
481 if (AndRectRect(&r, clip, &clipped_r))
483 InvertPixelArray(rp, clipped_r.MinX, clipped_r.MinY,
484 clipped_r.MaxX - clipped_r.MinX + 1, clipped_r.MaxY - clipped_r.MinY + 1);
489 ///IconList_InvertLassoOutlines()
490 // Simple lasso drawing by inverting area outlines
491 static void IconList_InvertLassoOutlines(Object *obj, struct IconList_DATA *data, struct Rectangle *rect)
493 struct Rectangle lasso;
494 struct Rectangle clip;
496 #if defined(DEBUG_ILC_LASSO) || defined(DEBUG_ILC_FUNCS)
497 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
498 #endif
500 /* get abolute iconlist coords */
501 lasso.MinX = rect->MinX + _mleft(obj);
502 lasso.MaxX = rect->MaxX + _mleft(obj);
503 lasso.MinY = rect->MinY + _mtop(obj);
504 lasso.MaxY = rect->MaxY + _mtop(obj);
506 clip.MinX = _mleft(obj);
507 clip.MinY = _mtop(obj);
508 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
510 clip.MinY += data->icld_LVMAttribs->lmva_HeaderHeight;
512 clip.MaxX = _mright(obj);
513 clip.MaxY = _mbottom(obj);
515 /* horizontal lasso lines */
516 IconList_InvertPixelRect(_rp(obj), lasso.MinX + 2, lasso.MinY, lasso.MaxX - 1, lasso.MinY + 1, &clip);
517 IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MaxY, lasso.MaxX + 1, lasso.MaxY + 1, &clip);
519 /* vertical lasso lines */
520 IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MinY, lasso.MinX + 1, lasso.MaxY - 1, &clip);
521 IconList_InvertPixelRect(_rp(obj), lasso.MaxX, lasso.MinY, lasso.MaxX + 1, lasso.MaxY - 1, &clip);
525 ///IconList_GetIconImageRectangle()
526 //We don't use icon.library's label drawing so we do this by hand
527 static void IconList_GetIconImageRectangle(Object *obj, struct IconList_DATA *data, struct IconEntry *entry, struct Rectangle *rect)
529 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
530 D(bug("[IconList]: %s(entry @ %p)\n", __PRETTY_FUNCTION__, entry));
531 #endif
533 /* Get basic width/height */
534 GetIconRectangleA(NULL, entry->ie_DiskObj, NULL, rect, __iconList_DrawIconStateTags);
535 #if defined(DEBUG_ILC_ICONPOSITIONING)
536 D(bug("[IconList] %s: MinX %d, MinY %d MaxX %d, MaxY %d\n", __PRETTY_FUNCTION__, rect->MinX, rect->MinY, rect->MaxX, rect->MaxY));
537 #endif
538 entry->ie_IconWidth = (rect->MaxX - rect->MinX) + 1;
539 entry->ie_IconHeight = (rect->MaxY - rect->MinY) + 1;
541 if (entry->ie_IconHeight > data->icld_IconLargestHeight)
542 data->icld_IconLargestHeight = entry->ie_IconHeight;
546 ///IconList_GetIconImageOffsets()
547 static void IconList_GetIconImageOffsets(struct IconList_DATA *data, struct IconEntry *entry, LONG *offsetx, LONG *offsety)
549 *offsetx = *offsety = 0;
550 if (entry->ie_IconWidth < entry->ie_AreaWidth)
551 *offsetx += (entry->ie_AreaWidth - entry->ie_IconWidth)/2;
553 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
554 (entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
555 *offsetx += ((data->icld_IconAreaLargestWidth - entry->ie_AreaWidth)/2);
557 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
558 (entry->ie_AreaHeight < data->icld_IconAreaLargestHeight))
559 *offsety += ((data->icld_IconAreaLargestHeight - entry->ie_AreaHeight)/2);
562 ///IconList_GetIconLabelRectangle()
563 static void IconList_GetIconLabelRectangle(Object *obj, struct IconList_DATA *data, struct IconEntry *entry, struct Rectangle *rect)
565 ULONG outline_offset = 0;
566 ULONG textwidth = 0;
568 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
569 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
570 #endif
572 switch ( data->icld__Option_LabelTextMode )
574 case ICON_TEXTMODE_DROPSHADOW:
575 outline_offset = 1;
576 break;
578 case ICON_TEXTMODE_PLAIN:
579 break;
581 default:
582 outline_offset = 2;
583 break;
586 /* Get entry box width including text width */
587 if ((entry->ie_IconListEntry.label != NULL) && (entry->ie_TxtBuf_DisplayedLabel != NULL))
589 ULONG curlabel_TotalLines;
590 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
592 rect->MinX = 0;
593 rect->MaxX = (((data->icld__Option_LabelTextHorizontalPadding + data->icld__Option_LabelTextBorderWidth) * 2) + entry->ie_TxtBuf_DisplayedLabelWidth + outline_offset) - 1;
595 rect->MinY = 0;
597 curlabel_TotalLines = entry->ie_SplitParts;
598 if (curlabel_TotalLines == 0)
599 curlabel_TotalLines = 1;
600 if (curlabel_TotalLines > data->icld__Option_LabelTextMultiLine)
601 curlabel_TotalLines = data->icld__Option_LabelTextMultiLine;
603 rect->MaxY = (((data->icld__Option_LabelTextBorderHeight + data->icld__Option_LabelTextVerticalPadding) * 2) +
604 ((data->icld_IconLabelFont->tf_YSize + outline_offset) * curlabel_TotalLines)) - 1;
606 /* Date/size sorting has the date/size appended under the entry label
607 only list regular files like this (drawers have no size/date output) */
609 entry->ie_IconListEntry.type != ST_USERDIR &&
610 ((data->icld_SortFlags & MUIV_IconList_Sort_BySize) || (data->icld_SortFlags & MUIV_IconList_Sort_ByDate))
613 SetFont(data->icld_BufferRastPort, data->icld_IconInfoFont);
615 if( (data->icld_SortFlags & MUIV_IconList_Sort_BySize) && !(data->icld_SortFlags & MUIV_IconList_Sort_ByDate) )
617 entry->ie_TxtBuf_SIZEWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_SIZE, strlen(entry->ie_TxtBuf_SIZE));
618 textwidth = entry->ie_TxtBuf_SIZEWidth;
620 else
622 if( !(data->icld_SortFlags & MUIV_IconList_Sort_BySize) && (data->icld_SortFlags & MUIV_IconList_Sort_ByDate) )
624 if( entry->ie_Flags & ICONENTRY_FLAG_TODAY )
626 entry->ie_TxtBuf_TIMEWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_TIME, strlen(entry->ie_TxtBuf_TIME));
627 textwidth = entry->ie_TxtBuf_TIMEWidth;
629 else
631 entry->ie_TxtBuf_DATEWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_DATE, strlen(entry->ie_TxtBuf_DATE));
632 textwidth = entry->ie_TxtBuf_DATEWidth;
637 if (textwidth > 0)
639 rect->MaxY = rect->MaxY + data->icld_IconInfoFont->tf_YSize + outline_offset;
640 if ((textwidth + outline_offset + ((data->icld__Option_LabelTextHorizontalPadding + data->icld__Option_LabelTextBorderWidth) * 2)) > ((rect->MaxX - rect->MinX) + 1))
641 rect->MaxX = (textwidth + outline_offset + ((data->icld__Option_LabelTextVerticalPadding + data->icld__Option_LabelTextBorderWidth) * 2)) - 1;
645 if (((rect->MaxY - rect->MinY) + 1) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = ((rect->MaxY - rect->MinY) + 1);
649 ///IconList_GetIconAreaRectangle()
650 static void IconList_GetIconAreaRectangle(Object *obj, struct IconList_DATA *data, struct IconEntry *entry, struct Rectangle *rect)
652 struct Rectangle labelrect;
653 ULONG iconlabel_Width;
654 ULONG iconlabel_Height;
656 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
657 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
658 #endif
660 /* Get entry box width including text width */
661 memset(rect, 0, sizeof(struct Rectangle));
663 IconList_GetIconImageRectangle(obj, data, entry, rect);
665 entry->ie_AreaWidth = entry->ie_IconWidth;
666 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
668 entry->ie_AreaHeight = data->icld_IconLargestHeight;
670 else
672 entry->ie_AreaHeight = entry->ie_IconHeight;
675 IconList_GetIconLabelRectangle(obj, data, entry, &labelrect);
677 iconlabel_Width = ((labelrect.MaxX - labelrect.MinX) + 1);
678 iconlabel_Height = ((labelrect.MaxY - labelrect.MinY) + 1);
680 if (iconlabel_Width > entry->ie_AreaWidth)
681 entry->ie_AreaWidth = iconlabel_Width;
683 entry->ie_AreaHeight = entry->ie_AreaHeight + data->icld__Option_IconImageSpacing + iconlabel_Height;
685 /* Store */
686 rect->MaxX = (rect->MinX + entry->ie_AreaWidth) - 1;
687 rect->MaxY = (rect->MinY + entry->ie_AreaHeight) - 1;
689 if (entry->ie_AreaWidth > data->icld_IconAreaLargestWidth) data->icld_IconAreaLargestWidth = entry->ie_AreaWidth;
690 if (entry->ie_AreaHeight > data->icld_IconAreaLargestHeight) data->icld_IconAreaLargestHeight = entry->ie_AreaHeight;
694 static LONG FirstVisibleColumnNumber(struct IconList_DATA *data)
696 LONG i;
697 LONG retval = -1;
699 if (data->icld_LVMAttribs != NULL)
701 for(i = 0; i < NUM_COLUMNS; i++)
703 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
705 if (data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)
707 retval = i;
708 break;
713 return retval;
716 static LONG LastVisibleColumnNumber(struct IconList_DATA *data)
718 LONG i;
719 LONG retval = -1;
721 if (data->icld_LVMAttribs != NULL)
723 for(i = 0; i < NUM_COLUMNS; i++)
725 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
727 if (data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)
729 retval = i;
734 return retval;
738 ///NullifyLasso()
739 // Remove the lasso from the screen
740 static void NullifyLasso(struct IconList_DATA *data, Object *obj)
742 /* End Lasso-selection */
743 struct Rectangle old_lasso;
744 struct IconEntry *node = NULL;
745 struct Window *thisWindow = NULL;
747 #if defined(DEBUG_ILC_EVENTS) || defined(DEBUG_ILC_LASSO)
748 D(bug("[IconList] %s: Removing Lasso\n", __PRETTY_FUNCTION__));
749 #endif
751 /* Stop handling INTUITICKS */
752 GET(obj, MUIA_Window, &thisWindow);
753 if (thisWindow)
755 ModifyIDCMP(thisWindow, (thisWindow->IDCMPFlags & ~(IDCMP_INTUITICKS)));
756 if ((data->ehn.ehn_Events & IDCMP_INTUITICKS))
758 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
759 data->ehn.ehn_Events &= ~IDCMP_INTUITICKS;
760 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
764 /* Clear Lasso Frame.. */
765 GetAbsoluteLassoRect(data, &old_lasso);
766 IconList_InvertLassoOutlines(obj, data, &old_lasso);
768 data->icld_LassoActive = FALSE;
770 /* Remove Lasso flag from affected icons.. */
771 #if defined(__AROS__)
772 ForeachNode(&data->icld_IconList, node)
773 #else
774 Foreach_Node(&data->icld_IconList, node);
775 #endif
777 if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
779 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
782 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
786 static void RenderEntryField(Object *obj, struct IconList_DATA *data,
787 struct IconEntry *entry, struct Rectangle *rect, LONG index, BOOL firstvis,
788 BOOL lastvis, struct RastPort * rp)
790 STRPTR text = NULL, renderflag = "<UHOH>";
791 struct TextExtent te;
792 ULONG fit;
794 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
796 FillPixelArray(rp,
797 rect->MinX, rect->MinY,
798 rect->MaxX - rect->MinX + 1, rect->MaxY - rect->MinY,
799 0x0A246A);
802 rect->MinX += ENTRY_SPACING_LEFT;
803 rect->MaxX -= ENTRY_SPACING_RIGHT;
804 rect->MinY += LINE_SPACING_TOP;
805 rect->MaxY -= LINE_SPACING_BOTTOM;
807 if (firstvis) rect->MinX += LINE_SPACING_LEFT;
808 if (lastvis) rect->MaxX -= LINE_SPACING_RIGHT;
810 if (!entry) return;
812 switch(index)
814 case INDEX_TYPE:
815 /* Special case !! we draw an image instead .. */
816 text = renderflag;
817 break;
819 case INDEX_NAME:
820 text = entry->ie_IconListEntry.label;
821 break;
823 case INDEX_SIZE:
824 text = entry->ie_TxtBuf_SIZE;
825 break;
827 case INDEX_LASTACCESS:
828 text = AllocVec(strlen(entry->ie_TxtBuf_DATE) + strlen(entry->ie_TxtBuf_TIME) + 5, MEMF_CLEAR);
829 if (text)
830 sprintf(text, "%s %s", entry->ie_TxtBuf_DATE,
831 entry->ie_TxtBuf_TIME);
832 break;
834 case INDEX_COMMENT:
835 text = entry->ie_FileInfoBlock->fib_Comment;
836 break;
838 case INDEX_PROTECTION:
839 text = entry->ie_TxtBuf_PROT;
840 break;
843 if (!text) return;
844 if (!text[0]) return;
846 if (text == renderflag)
848 if (entry->ie_IconListEntry.type == ST_USERDIR)
850 if (data->icld_LVMAttribs->lvma_IconDrawer)
852 DrawIconStateA
854 rp, data->icld_LVMAttribs->lvma_IconDrawer, NULL,
855 rect->MinX + 1, rect->MinY + 1,
856 (entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
857 __iconList_DrawIconStateTags
860 else
862 FillPixelArray(rp,
863 rect->MinX + 1, rect->MinY + 1,
864 rect->MaxX - rect->MinX - 1, rect->MaxY - rect->MinY - 1,
865 0xc0f0f0);
868 else
870 if (data->icld_LVMAttribs->lvma_IconFile)
872 DrawIconStateA
874 rp, data->icld_LVMAttribs->lvma_IconFile, NULL,
875 rect->MinX + 1, rect->MinY + 1,
876 (entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
877 __iconList_DrawIconStateTags
880 else
882 FillPixelArray(rp,
883 rect->MinX + 1, rect->MinY + 1,
884 rect->MaxX - rect->MinX - 1, rect->MaxY - rect->MinY - 1,
885 0xe0e0e0);
889 else
891 fit = TextFit(rp, text, strlen(text), &te, NULL, 1,
892 rect->MaxX - rect->MinX + 1,
893 rect->MaxY - rect->MinY + 1);
895 if (!fit) return;
897 SetABPenDrMd(rp, _pens(obj)[(entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? MPEN_SHINE : MPEN_TEXT], 0, JAM1);
899 if (((rect->MaxY - rect->MinY + 1) - data->icld_IconLabelFont->tf_YSize) > 0)
901 rect->MinY += ((rect->MaxY - rect->MinY + 1) - data->icld_IconLabelFont->tf_YSize) / 2;
904 switch(data->icld_LVMAttribs->lmva_ColumnHAlign[index])
906 case COLUMN_ALIGN_LEFT:
907 Move(rp, rect->MinX, rect->MinY + rp->TxBaseline);
908 break;
910 case COLUMN_ALIGN_RIGHT:
911 Move(rp, rect->MaxX - te.te_Width, rect->MinY + rp->TxBaseline);
912 break;
914 case COLUMN_ALIGN_CENTER:
915 Move(rp, rect->MinX + (rect->MaxX - rect->MinX + 1 + 1 - te.te_Width) / 2,
916 rect->MinY + rp->TxBaseline);
917 break;
920 Text(rp, text, fit);
922 if ((index == INDEX_LASTACCESS) && text)
923 FreeVec(text);
927 /**************************************************************************
928 Draw the entry at its position
929 **************************************************************************/
930 ///IconList__MUIM_IconList_DrawEntry()
931 IPTR IconList__MUIM_IconList_DrawEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DrawEntry *message)
933 struct IconList_DATA *data = INST_DATA(CLASS, obj);
935 BOOL outside = FALSE;
937 struct Rectangle iconrect;
938 struct Rectangle objrect;
940 ULONG objX, objY, objW, objH;
941 LONG iconX, iconY;
943 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
945 objX = _mleft(obj);
946 objY = _mtop(obj);
948 else
950 objX = objY = 0;
952 objW = _mright(obj) - _mleft(obj) + 1;
953 objH = _mbottom(obj) - _mtop(obj) + 1;
955 #if defined(DEBUG_ILC_ICONRENDERING)
956 D(bug("[IconList]: %s(message->entry = 0x%p)\n", __PRETTY_FUNCTION__, message->entry));
957 #endif
959 if ((!(message->entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)) ||
960 (data->icld_BufferRastPort == NULL) ||
961 (!(message->entry->ie_DiskObj)))
963 #if defined(DEBUG_ILC_ICONRENDERING)
964 D(bug("[IconList] %s: Not visible or missing DOB\n", __PRETTY_FUNCTION__));
965 #endif
966 return FALSE;
969 /* Set the dimensions of our "view" */
970 objrect.MinX = objX;
971 objrect.MinY = objY;
972 objrect.MaxX = objX + objW - 1;
973 objrect.MaxY = objY + objH - 1;
975 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
977 struct Rectangle linerect;
978 LONG x, i;
979 LONG firstvis, lastvis;
981 linerect.MinX = objX - data->icld_ViewX;
982 linerect.MaxX = objX + objW - 1; //linerect.MinX + data->width - 1;
983 linerect.MinY = (objY - data->icld_ViewY) + data->icld_LVMAttribs->lmva_HeaderHeight + (message->drawmode * data->icld_LVMAttribs->lmva_RowHeight);
984 linerect.MaxY = linerect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
986 if (!AndRectRect(&linerect, &objrect, NULL)) return FALSE;
987 // if (!MustRenderRect(data, &linerect)) return;
989 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
991 x = linerect.MinX + LINE_SPACING_LEFT;
993 firstvis = FirstVisibleColumnNumber(data);
994 lastvis = LastVisibleColumnNumber(data);
996 for(i = 0; i < NUM_COLUMNS; i++)
998 struct Rectangle field_rect;
999 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
1001 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[i] & LVMCF_COLVISIBLE)) continue;
1003 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
1004 field_rect.MinY = linerect.MinY;
1005 field_rect.MaxX = x + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1 + ((i == lastvis) ? LINE_SPACING_RIGHT : 0);
1006 field_rect.MaxY = linerect.MaxY;
1008 /* if (MustRenderRect(data, &field_rect))
1010 if (AndRectRect(&field_rect, &objrect, NULL))
1012 RenderEntryField(obj, data, message->entry, &field_rect, index,
1013 (i == firstvis), (i == lastvis), data->icld_BufferRastPort);
1015 /* }*/
1016 x += data->icld_LVMAttribs->lmva_ColumnWidth[index];
1019 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_ROWDRAWTOEND) == LVMAF_ROWDRAWTOEND)
1021 x += LINE_SPACING_RIGHT;
1023 if (x < linerect.MaxX)
1025 linerect.MinX = x;
1027 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_SHINE], 0, JAM1);
1028 RectFill(data->icld_BufferRastPort, linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
1032 else
1034 LONG offsetx,offsety;
1036 /* Get the dimensions and affected area of message->entry */
1037 IconList_GetIconImageRectangle(obj, data, message->entry, &iconrect);
1039 /* Get offset corrections */
1040 IconList_GetIconImageOffsets(data, message->entry, &offsetx, &offsety);
1042 /* Add the relative position offset of the message->entry */
1043 iconrect.MinX += objX - data->icld_ViewX + message->entry->ie_IconX + offsetx;
1044 iconrect.MaxX += objX - data->icld_ViewX + message->entry->ie_IconX + offsetx;
1045 iconrect.MinY += objY - data->icld_ViewY + message->entry->ie_IconY + offsety;
1046 iconrect.MaxY += objY - data->icld_ViewY + message->entry->ie_IconY + offsety;
1048 if (!RectAndRect(&iconrect, &objrect))
1050 #if defined(DEBUG_ILC_ICONRENDERING)
1051 D(bug("[IconList] %s: Entry '%s' image outside of visible area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1052 #endif
1053 return FALSE;
1056 /* data->update_rect1 and data->update_rect2 may
1057 point to rectangles to indicate that only icons
1058 in any of this rectangles need to be drawn */
1059 if (data->update_rect1)
1061 if (!RectAndRect(&iconrect, data->update_rect1)) outside = TRUE;
1064 if (data->update_rect2)
1066 if (data->update_rect1)
1068 if ((outside == TRUE) && RectAndRect(&iconrect, data->update_rect2))
1069 outside = FALSE;
1071 else
1073 if (!RectAndRect(&iconrect, data->update_rect2))
1074 outside = TRUE;
1078 if (outside == TRUE)
1080 #if defined(DEBUG_ILC_ICONRENDERING)
1081 D(bug("[IconList] %s: Entry '%s' image outside of update area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1082 #endif
1083 return FALSE;
1086 if (message->drawmode == ICONENTRY_DRAWMODE_NONE) return TRUE;
1088 // Center entry image
1089 iconX = iconrect.MinX - objX + data->icld_DrawOffsetX;
1090 iconY = iconrect.MinY - objY + data->icld_DrawOffsetY;
1092 #if defined(DEBUG_ILC_ICONRENDERING)
1093 D(bug("[IconList] %s: DrawIconState('%s') .. %d, %d\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label, iconX, iconY));
1094 #endif
1095 DrawIconStateA
1097 data->icld_BufferRastPort, message->entry->ie_DiskObj, NULL,
1098 iconX,
1099 iconY,
1100 (message->entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
1101 __iconList_DrawIconStateTags
1103 #if defined(DEBUG_ILC_ICONRENDERING)
1104 D(bug("[IconList] %s: DrawIconState Done\n", __PRETTY_FUNCTION__));
1105 #endif
1108 return TRUE;
1112 ///IconList__LabelFunc_SplitLabel()
1113 static void IconList__LabelFunc_SplitLabel(Object *obj, struct IconList_DATA *data, struct IconEntry *entry)
1115 ULONG labelSplit_MaxLabelLineLength = data->icld__Option_LabelTextMaxLen;
1116 ULONG labelSplit_LabelLength = strlen(entry->ie_IconListEntry.label);
1117 ULONG txwidth;
1118 // ULONG labelSplit_FontY = data->icld_IconLabelFont->tf_YSize;
1119 int labelSplit_CharsDone, labelSplit_CharsSplit;
1120 ULONG labelSplit_CurSplitWidth;
1122 if ((data->icld__Option_TrimVolumeNames) &&
1123 ((entry->ie_IconListEntry.type == ST_ROOT) && (entry->ie_IconListEntry.label[labelSplit_LabelLength - 1] == ':')))
1124 labelSplit_LabelLength--;
1126 if (labelSplit_MaxLabelLineLength >= labelSplit_LabelLength)
1128 #if defined(DEBUG_ILC_ICONRENDERING)
1129 D(bug("[IconList]: %s: Label'%s' doesnt need split (onyl %d chars)\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label, labelSplit_LabelLength));
1130 #endif
1131 return;
1134 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
1135 txwidth = TextLength(data->icld_BufferRastPort, entry->ie_IconListEntry.label, labelSplit_MaxLabelLineLength);
1136 #if defined(DEBUG_ILC_ICONRENDERING)
1137 D(bug("[IconList]: %s: txwidth = %d\n", __PRETTY_FUNCTION__, txwidth));
1138 #endif
1139 entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, 256);
1140 if (entry->ie_TxtBuf_DisplayedLabel != NULL)
1141 memset(entry->ie_TxtBuf_DisplayedLabel, 0, 256);
1142 entry->ie_SplitParts = 0;
1144 labelSplit_CharsDone = 0;
1145 labelSplit_CharsSplit = 0;
1146 labelSplit_CurSplitWidth = 0;
1148 while (labelSplit_CharsDone < labelSplit_LabelLength)
1150 ULONG labelSplit_CurSplitLength = labelSplit_LabelLength - labelSplit_CharsDone;
1151 IPTR labelSplit_SplitStart = (IPTR)(entry->ie_IconListEntry.label + labelSplit_CharsDone);
1152 int tmp_checkoffs = 0;
1153 IPTR labelSplit_RemainingCharsAfterSplit = 0;
1154 IPTR labelSplit_CurSplitDest;
1156 while (*(char *)(labelSplit_SplitStart) == ' ')
1158 //Skip preceding spaces..
1159 labelSplit_SplitStart = labelSplit_SplitStart + 1;
1160 labelSplit_CurSplitLength = labelSplit_CurSplitLength - 1;
1161 labelSplit_CharsDone = labelSplit_CharsDone + 1;
1164 while(TextLength(data->icld_BufferRastPort, (char *)labelSplit_SplitStart, labelSplit_CurSplitLength) < txwidth) labelSplit_CurSplitLength++;
1165 while(TextLength(data->icld_BufferRastPort, (char *)labelSplit_SplitStart, labelSplit_CurSplitLength) > txwidth) labelSplit_CurSplitLength--;
1166 #if defined(DEBUG_ILC_ICONRENDERING)
1167 D(bug("[IconList]: %s: labelSplit_CurSplitLength = %d\n", __PRETTY_FUNCTION__, labelSplit_CurSplitLength));
1168 #endif
1170 #if defined(DEBUG_ILC_ICONRENDERING)
1171 D(bug("[IconList]: %s: Attempting to find neat split ", __PRETTY_FUNCTION__));
1172 #endif
1173 while(tmp_checkoffs < (labelSplit_CurSplitLength - ILC_ICONLABEL_SHORTEST))
1175 #if defined(DEBUG_ILC_ICONRENDERING)
1176 D(bug("%d", tmp_checkoffs));
1177 #endif
1178 labelSplit_RemainingCharsAfterSplit = labelSplit_LabelLength - (labelSplit_CharsDone + labelSplit_CurSplitLength);
1180 if ((labelSplit_CurSplitLength - tmp_checkoffs) > ILC_ICONLABEL_SHORTEST)
1182 #if defined(DEBUG_ILC_ICONRENDERING)
1183 D(bug("<"));
1184 #endif
1185 if ((*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == ' ') ||
1186 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == '.') ||
1187 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == '-'))
1189 #if defined(DEBUG_ILC_ICONRENDERING)
1190 D(bug("!"));
1191 #endif
1192 labelSplit_CurSplitLength = labelSplit_CurSplitLength - tmp_checkoffs;
1193 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit - tmp_checkoffs;
1194 tmp_checkoffs = 0;
1195 break;
1199 if ((labelSplit_RemainingCharsAfterSplit - tmp_checkoffs) < 0)
1201 #if defined(DEBUG_ILC_ICONRENDERING)
1202 D(bug("="));
1203 #endif
1204 labelSplit_CurSplitLength = labelSplit_CurSplitLength + tmp_checkoffs;
1205 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit + tmp_checkoffs;
1206 tmp_checkoffs = 0;
1207 break;
1210 if ((labelSplit_RemainingCharsAfterSplit - tmp_checkoffs) >= ILC_ICONLABEL_SHORTEST)
1212 #if defined(DEBUG_ILC_ICONRENDERING)
1213 D(bug(">"));
1214 #endif
1215 if ((*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == ' ') ||
1216 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == '.') ||
1217 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == '-'))
1219 #if defined(DEBUG_ILC_ICONRENDERING)
1220 D(bug("!"));
1221 #endif
1222 labelSplit_CurSplitLength = labelSplit_CurSplitLength + tmp_checkoffs;
1223 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit + tmp_checkoffs;
1224 tmp_checkoffs = 0;
1225 break;
1229 tmp_checkoffs = tmp_checkoffs + 1;
1231 #if defined(DEBUG_ILC_ICONRENDERING)
1232 D(bug("\n"));
1233 #endif
1234 if (tmp_checkoffs != 0)
1236 #if defined(DEBUG_ILC_ICONRENDERING)
1237 D(bug("[IconList]: %s: Couldnt find neat split : Still %d chars\n", __PRETTY_FUNCTION__, labelSplit_RemainingCharsAfterSplit));
1238 #endif
1239 if (labelSplit_RemainingCharsAfterSplit <= ILC_ICONLABEL_SHORTEST)
1241 labelSplit_CurSplitLength = labelSplit_CurSplitLength + (labelSplit_RemainingCharsAfterSplit - ILC_ICONLABEL_SHORTEST);
1244 if ((labelSplit_CharsDone + labelSplit_CurSplitLength) > labelSplit_LabelLength) labelSplit_CurSplitLength = labelSplit_LabelLength - labelSplit_CharsDone;
1246 if (entry->ie_TxtBuf_DisplayedLabel != NULL)
1248 labelSplit_CurSplitDest = (IPTR)(entry->ie_TxtBuf_DisplayedLabel
1249 + labelSplit_CharsSplit + entry->ie_SplitParts);
1251 strncpy((char *)labelSplit_CurSplitDest,
1252 (char *)labelSplit_SplitStart, labelSplit_CurSplitLength);
1254 labelSplit_CurSplitWidth = TextLength(data->icld_BufferRastPort,
1255 (char *)labelSplit_CurSplitDest, labelSplit_CurSplitLength);
1258 entry->ie_SplitParts = entry->ie_SplitParts + 1;
1260 labelSplit_CharsDone = labelSplit_CharsDone + labelSplit_CurSplitLength;
1261 labelSplit_CharsSplit = labelSplit_CharsSplit + labelSplit_CurSplitLength;
1263 if (labelSplit_CurSplitWidth > entry->ie_TxtBuf_DisplayedLabelWidth) entry->ie_TxtBuf_DisplayedLabelWidth = labelSplit_CurSplitWidth;
1265 if ((entry->ie_SplitParts <= 1) && entry->ie_TxtBuf_DisplayedLabel)
1267 FreeVecPooled(data->icld_Pool, entry->ie_TxtBuf_DisplayedLabel);
1268 entry->ie_TxtBuf_DisplayedLabel = NULL;
1269 entry->ie_SplitParts = 0;
1271 // if ((labelSplit_FontY * entry->ie_SplitParts) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = (labelSplit_FontY * entry->ie_SplitParts);
1275 ///IconList__LabelFunc_CreateLabel()
1276 static IPTR IconList__LabelFunc_CreateLabel(Object *obj, struct IconList_DATA *data, struct IconEntry *entry)
1278 #if defined(DEBUG_ILC_ICONRENDERING) || defined(DEBUG_ILC_FUNCS)
1279 D(bug("[IconList]: %s('%s')\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label));
1280 #endif
1281 if (entry->ie_TxtBuf_DisplayedLabel)
1283 FreeVecPooled(data->icld_Pool, entry->ie_TxtBuf_DisplayedLabel);
1284 entry->ie_TxtBuf_DisplayedLabel = NULL;
1285 entry->ie_SplitParts = 0;
1288 if (data->icld__Option_LabelTextMultiLine > 1)
1290 #if defined(DEBUG_ILC_ICONRENDERING)
1291 D(bug("[IconList]: %s: Attempting to split label ..\n", __PRETTY_FUNCTION__));
1292 #endif
1293 IconList__LabelFunc_SplitLabel(obj, data, entry);
1296 if (entry->ie_TxtBuf_DisplayedLabel == NULL)
1298 ULONG ie_LabelLength = strlen(entry->ie_IconListEntry.label);
1299 entry->ie_SplitParts = 1;
1301 #if defined(DEBUG_ILC_ICONRENDERING)
1302 D(bug("[IconList]: %s: Building unsplit label (len = %d) ..\n", __PRETTY_FUNCTION__, ie_LabelLength));
1303 #endif
1305 if ((data->icld__Option_TrimVolumeNames) &&
1306 ((entry->ie_IconListEntry.type == ST_ROOT) && (entry->ie_IconListEntry.label[ie_LabelLength - 1] == ':')))
1307 ie_LabelLength--;
1309 if(ie_LabelLength > data->icld__Option_LabelTextMaxLen)
1311 if (!(entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, data->icld__Option_LabelTextMaxLen + 1)))
1313 return (IPTR)NULL;
1315 memset(entry->ie_TxtBuf_DisplayedLabel, 0, data->icld__Option_LabelTextMaxLen + 1);
1316 strncpy(entry->ie_TxtBuf_DisplayedLabel, entry->ie_IconListEntry.label, data->icld__Option_LabelTextMaxLen - 3);
1317 strcat(entry->ie_TxtBuf_DisplayedLabel , " ..");
1319 else
1321 if (!(entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, ie_LabelLength + 1)))
1323 return (IPTR)NULL;
1325 memset(entry->ie_TxtBuf_DisplayedLabel, 0, ie_LabelLength + 1);
1326 strncpy(entry->ie_TxtBuf_DisplayedLabel, entry->ie_IconListEntry.label, ie_LabelLength );
1328 entry->ie_TxtBuf_DisplayedLabelWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_DisplayedLabel, strlen(entry->ie_TxtBuf_DisplayedLabel));
1329 // if ((data->icld_IconLabelFont->tf_YSize) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = data->icld_IconLabelFont->tf_YSize;
1332 // if (entry->ie_TxtBuf_DisplayedLabelWidth > data->icld_LabelLargestWidth) data->icld_LabelLargestWidth = entry->ie_TxtBuf_DisplayedLabelWidth;
1334 return (IPTR)entry->ie_TxtBuf_DisplayedLabel;
1338 ///IconList__HookFunc_UpdateLabelsFunc()
1339 AROS_UFH3(
1340 void, IconList__HookFunc_UpdateLabelsFunc,
1341 AROS_UFHA(struct Hook *, hook, A0),
1342 AROS_UFHA(APTR *, obj, A2),
1343 AROS_UFHA(APTR, param, A1)
1346 AROS_USERFUNC_INIT
1348 /* Get our private data */
1349 Class *CLASS = *( Class **)param;
1350 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1352 #if defined(DEBUG_ILC_LASSO) || defined(DEBUG_ILC_FUNCS)
1353 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1354 #endif
1356 if (((data->icld__Option_LabelTextMaxLen != data->icld__Option_LastLabelTextMaxLen) &&
1357 (data->icld__Option_LabelTextMultiLine > 1)) ||
1358 (data->icld__Option_LabelTextMultiLine != data->icld__Option_LastLabelTextMultiLine));
1360 struct IconEntry *iconentry_Current = NULL;
1361 #if defined(__AROS__)
1362 ForeachNode(&data->icld_IconList, iconentry_Current)
1363 #else
1364 Foreach_Node(&data->icld_IconList, iconentry_Current);
1365 #endif
1367 IconList__LabelFunc_CreateLabel((Object *)obj, data, iconentry_Current);
1371 data->icld__Option_LastLabelTextMaxLen = data->icld__Option_LabelTextMaxLen;
1372 data->icld__Option_LastLabelTextMultiLine = data->icld__Option_LabelTextMultiLine;
1374 AROS_USERFUNC_EXIT
1378 ///IconList__MUIM_IconList_DrawEntryLabel()
1379 IPTR IconList__MUIM_IconList_DrawEntryLabel(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DrawEntry *message)
1381 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1383 STRPTR buf = NULL;
1384 BOOL outside = FALSE;
1386 struct Rectangle iconlabelrect;
1387 struct Rectangle objrect;
1389 ULONG txtbox_width = 0;
1390 LONG tx,ty,offsetx,offsety;
1391 LONG txwidth; // txheight;
1393 ULONG objX, objY, objW, objH;
1394 LONG labelX, labelY;
1396 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1397 return FALSE;
1399 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
1401 objX = _mleft(obj);
1402 objY = _mtop(obj);
1404 else
1406 objX = objY = 0;
1408 objW = _mright(obj) - _mleft(obj) + 1;
1409 objH = _mbottom(obj) - _mtop(obj) + 1;
1411 ULONG txtarea_width;
1412 ULONG curlabel_TotalLines, curlabel_CurrentLine, offset_y;
1414 #if defined(DEBUG_ILC_ICONRENDERING) || defined(DEBUG_ILC_FUNCS)
1415 D(bug("[IconList]: %s(message->entry = 0x%p), '%s'\n", __PRETTY_FUNCTION__, message->entry, message->entry->ie_IconListEntry.label));
1416 #endif
1418 if ((!(message->entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)) ||
1419 (data->icld_BufferRastPort == NULL) ||
1420 (!(message->entry->ie_DiskObj)))
1422 #if defined(DEBUG_ILC_ICONRENDERING)
1423 D(bug("[IconList] %s: Not visible or missing DOB\n", __PRETTY_FUNCTION__));
1424 #endif
1425 return FALSE;
1428 /* Get the dimensions and affected area of message->entry's label */
1429 IconList_GetIconLabelRectangle(obj, data, message->entry, &iconlabelrect);
1431 /* Add the relative position offset of the message->entry's label */
1432 offsetx = (objX - data->icld_ViewX) + message->entry->ie_IconX;
1433 txtbox_width = (iconlabelrect.MaxX - iconlabelrect.MinX) + 1;
1435 if (txtbox_width < message->entry->ie_AreaWidth)
1436 offsetx += ((message->entry->ie_AreaWidth - txtbox_width)/2);
1438 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1439 (message->entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
1440 offsetx += ((data->icld_IconAreaLargestWidth - message->entry->ie_AreaWidth)/2);
1442 iconlabelrect.MinX += offsetx;
1443 iconlabelrect.MaxX += offsetx;
1445 offsety = (objY - data->icld_ViewY) + message->entry->ie_IconY + data->icld__Option_IconImageSpacing;
1446 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1447 (message->entry->ie_AreaHeight < data->icld_IconAreaLargestHeight))
1448 offsety += ((data->icld_IconAreaLargestHeight - message->entry->ie_AreaHeight)/2);
1450 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1452 offsety = offsety + data->icld_IconLargestHeight;
1454 else
1456 offsety = offsety + message->entry->ie_IconHeight;
1458 iconlabelrect.MinY += offsety;
1459 iconlabelrect.MaxY += offsety;
1461 /* Add the relative position of the window */
1462 objrect.MinX = objX;
1463 objrect.MinY = objX;
1464 objrect.MaxX = objX + objW;
1465 objrect.MaxY = objY + objH;
1467 if (!RectAndRect(&iconlabelrect, &objrect))
1469 #if defined(DEBUG_ILC_ICONRENDERING)
1470 (bug("[IconList] %s: Entry '%s' label outside of visible area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1471 #endif
1472 return FALSE;
1475 /* data->update_rect1 and data->update_rect2 may
1476 point to rectangles to indicate that only icons
1477 in any of this rectangles need to be drawn */
1478 if (data->update_rect1)
1480 if (!RectAndRect(&iconlabelrect, data->update_rect1))
1481 outside = TRUE;
1484 if (data->update_rect2)
1486 if (data->update_rect1)
1488 if ((outside == TRUE) && RectAndRect(&iconlabelrect, data->update_rect2))
1489 outside = FALSE;
1491 else
1493 if (!RectAndRect(&iconlabelrect, data->update_rect2))
1494 outside = TRUE;
1498 if (outside == TRUE)
1500 #if defined(DEBUG_ILC_ICONRENDERING)
1501 D(bug("[IconList] %s: Entry '%s' label outside of update area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1502 #endif
1503 return FALSE;
1506 if (message->drawmode == ICONENTRY_DRAWMODE_NONE)
1507 return TRUE;
1509 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_TEXT], 0, JAM1);
1511 iconlabelrect.MinX = (iconlabelrect.MinX - objX) + data->icld_DrawOffsetX;
1512 iconlabelrect.MinY = (iconlabelrect.MinY - objY) + data->icld_DrawOffsetY;
1513 iconlabelrect.MaxX = (iconlabelrect.MaxX - objX) + data->icld_DrawOffsetX;
1514 iconlabelrect.MaxY = (iconlabelrect.MaxY - objY) + data->icld_DrawOffsetY;
1516 labelX = iconlabelrect.MinX + data->icld__Option_LabelTextBorderWidth + data->icld__Option_LabelTextHorizontalPadding;
1517 labelY = iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight + data->icld__Option_LabelTextVerticalPadding;
1519 txtarea_width = txtbox_width - ((data->icld__Option_LabelTextBorderWidth + data->icld__Option_LabelTextHorizontalPadding) * 2);
1521 #if defined(DEBUG_ILC_ICONRENDERING)
1522 D(bug("[IconList] %s: Drawing Label '%s' .. %d, %d\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label, labelX, labelY));
1523 #endif
1524 if (message->entry->ie_IconListEntry.label && message->entry->ie_TxtBuf_DisplayedLabel)
1526 char *curlabel_StrPtr;
1528 if ((message->entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
1530 //Draw the focus box around the selected label ..
1531 if (data->icld__Option_LabelTextBorderHeight > 0)
1533 InvertPixelArray(data->icld_BufferRastPort,
1534 iconlabelrect.MinX, iconlabelrect.MinY,
1535 (iconlabelrect.MaxX - iconlabelrect.MinX) + 1, data->icld__Option_LabelTextBorderHeight);
1537 InvertPixelArray(data->icld_BufferRastPort,
1538 iconlabelrect.MinX, iconlabelrect.MaxY - (data->icld__Option_LabelTextBorderHeight - 1),
1539 (iconlabelrect.MaxX - iconlabelrect.MinX) + 1, data->icld__Option_LabelTextBorderHeight);
1541 if (data->icld__Option_LabelTextBorderWidth > 0)
1543 InvertPixelArray(data->icld_BufferRastPort,
1544 iconlabelrect.MinX, iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight,
1545 data->icld__Option_LabelTextBorderWidth, (((iconlabelrect.MaxY - iconlabelrect.MinY) + 1) - (data->icld__Option_LabelTextBorderHeight * 2)));
1547 InvertPixelArray(data->icld_BufferRastPort,
1548 iconlabelrect.MaxX - (data->icld__Option_LabelTextBorderWidth - 1), iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight,
1549 data->icld__Option_LabelTextBorderWidth, (((iconlabelrect.MaxY - iconlabelrect.MinY) + 1) - (data->icld__Option_LabelTextBorderHeight * 2)));
1553 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
1555 curlabel_TotalLines = message->entry->ie_SplitParts;
1556 curlabel_CurrentLine = 0;
1558 if (curlabel_TotalLines == 0)
1559 curlabel_TotalLines = 1;
1561 if (!(data->icld__Option_LabelTextMultiLineOnFocus) || (data->icld__Option_LabelTextMultiLineOnFocus && (message->entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
1563 if (curlabel_TotalLines > data->icld__Option_LabelTextMultiLine)
1564 curlabel_TotalLines = data->icld__Option_LabelTextMultiLine;
1566 else
1567 curlabel_TotalLines = 1;
1569 curlabel_StrPtr = message->entry->ie_TxtBuf_DisplayedLabel;
1571 ty = labelY - 1;
1573 #if defined(DEBUG_ILC_ICONRENDERING)
1574 D(bug("[IconList] %s: Font YSize %d Baseline %d\n", __PRETTY_FUNCTION__,data->icld_IconLabelFont->tf_YSize, data->icld_IconLabelFont->tf_Baseline));
1575 #endif
1576 for (curlabel_CurrentLine = 0; curlabel_CurrentLine < curlabel_TotalLines; curlabel_CurrentLine++)
1578 ULONG ie_LabelLength;
1580 if (curlabel_CurrentLine > 0) curlabel_StrPtr = curlabel_StrPtr + strlen(curlabel_StrPtr) + 1;
1581 if ((curlabel_CurrentLine >= (curlabel_TotalLines -1)) && (curlabel_TotalLines < message->entry->ie_SplitParts))
1583 char *tmpLine = curlabel_StrPtr;
1584 ULONG tmpLen = strlen(tmpLine);
1586 if ((curlabel_StrPtr = AllocVecPooled(data->icld_Pool, tmpLen + 1)) != NULL)
1588 memset(curlabel_StrPtr, 0, tmpLen + 1);
1589 strncpy(curlabel_StrPtr, tmpLine, tmpLen - 3);
1590 strcat(curlabel_StrPtr , " ..");
1592 else
1593 return FALSE;
1597 ie_LabelLength = strlen(curlabel_StrPtr);
1598 offset_y = 0;
1600 // Center message->entry's label
1601 tx = (labelX + (message->entry->ie_TxtBuf_DisplayedLabelWidth / 2) - (TextLength(data->icld_BufferRastPort, curlabel_StrPtr, strlen(curlabel_StrPtr)) / 2));
1603 if (message->entry->ie_TxtBuf_DisplayedLabelWidth < txtarea_width)
1604 tx += ((txtarea_width - message->entry->ie_TxtBuf_DisplayedLabelWidth)/2);
1606 ty = ty + data->icld_IconLabelFont->tf_YSize;
1608 switch ( data->icld__Option_LabelTextMode )
1610 case ICON_TEXTMODE_DROPSHADOW:
1611 SetAPen(data->icld_BufferRastPort, data->icld_LabelShadowPen);
1612 Move(data->icld_BufferRastPort, tx + 1, ty + 1);
1613 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1614 offset_y = 1;
1615 case ICON_TEXTMODE_PLAIN:
1616 SetAPen(data->icld_BufferRastPort, data->icld_LabelPen);
1617 Move(data->icld_BufferRastPort, tx, ty);
1618 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1619 break;
1621 default:
1622 // Outline mode:
1623 SetSoftStyle(data->icld_BufferRastPort, FSF_BOLD, AskSoftStyle(data->icld_BufferRastPort));
1625 SetAPen(data->icld_BufferRastPort, data->icld_LabelShadowPen);
1626 Move(data->icld_BufferRastPort, tx + 1, ty );
1627 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1628 Move(data->icld_BufferRastPort, tx - 1, ty );
1629 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1630 Move(data->icld_BufferRastPort, tx, ty + 1);
1631 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1632 Move(data->icld_BufferRastPort, tx, ty - 1);
1633 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1635 SetAPen(data->icld_BufferRastPort, data->icld_LabelPen);
1636 Move(data->icld_BufferRastPort, tx , ty );
1637 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1639 SetSoftStyle(data->icld_BufferRastPort, FS_NORMAL, AskSoftStyle(data->icld_BufferRastPort));
1640 offset_y = 2;
1641 break;
1643 if ((curlabel_CurrentLine >= (curlabel_TotalLines -1)) && (curlabel_TotalLines < message->entry->ie_SplitParts))
1645 FreeVecPooled(data->icld_Pool, curlabel_StrPtr);
1647 ty = ty + offset_y;
1650 /*date/size sorting has the date/size appended under the message->entry label*/
1652 if ((message->entry->ie_IconListEntry.type != ST_USERDIR) && ((data->icld_SortFlags & (MUIV_IconList_Sort_BySize|MUIV_IconList_Sort_ByDate)) != 0))
1654 buf = NULL;
1655 SetFont(data->icld_BufferRastPort, data->icld_IconInfoFont);
1657 if (data->icld_SortFlags & MUIV_IconList_Sort_BySize)
1659 buf = message->entry->ie_TxtBuf_SIZE;
1660 txwidth = message->entry->ie_TxtBuf_SIZEWidth;
1662 else if (data->icld_SortFlags & MUIV_IconList_Sort_ByDate)
1664 if (message->entry->ie_Flags & ICONENTRY_FLAG_TODAY)
1666 buf = message->entry->ie_TxtBuf_TIME;
1667 txwidth = message->entry->ie_TxtBuf_TIMEWidth;
1669 else
1671 buf = message->entry->ie_TxtBuf_DATE;
1672 txwidth = message->entry->ie_TxtBuf_DATEWidth;
1676 if (buf)
1678 ULONG ie_LabelLength = strlen(buf);
1679 tx = labelX;
1681 if (txwidth < txtarea_width)
1682 tx += ((txtarea_width - txwidth)/2);
1684 ty = labelY + ((data->icld__Option_LabelTextVerticalPadding + data->icld_IconLabelFont->tf_YSize ) * curlabel_TotalLines) + data->icld_IconInfoFont->tf_YSize;
1686 switch ( data->icld__Option_LabelTextMode )
1688 case ICON_TEXTMODE_DROPSHADOW:
1689 SetAPen(data->icld_BufferRastPort, data->icld_InfoShadowPen);
1690 Move(data->icld_BufferRastPort, tx + 1, ty + 1); Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1691 case ICON_TEXTMODE_PLAIN:
1692 SetAPen(data->icld_BufferRastPort, data->icld_InfoPen);
1693 Move(data->icld_BufferRastPort, tx, ty); Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1694 break;
1696 default:
1697 // Outline mode..
1698 SetSoftStyle(data->icld_BufferRastPort, FSF_BOLD, AskSoftStyle(data->icld_BufferRastPort));
1699 SetAPen(data->icld_BufferRastPort, data->icld_InfoShadowPen);
1701 Move(data->icld_BufferRastPort, tx + 1, ty );
1702 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1703 Move(data->icld_BufferRastPort, tx - 1, ty );
1704 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1705 Move(data->icld_BufferRastPort, tx, ty - 1 );
1706 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1707 Move(data->icld_BufferRastPort, tx, ty + 1 );
1708 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1710 SetAPen(data->icld_BufferRastPort, data->icld_InfoPen);
1712 Move(data->icld_BufferRastPort, tx, ty );
1713 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1715 SetSoftStyle(data->icld_BufferRastPort, FS_NORMAL, AskSoftStyle(data->icld_BufferRastPort));
1716 break;
1722 return TRUE;
1725 /**************************************************************************
1727 **************************************************************************/
1728 ///IconList__MUIM_IconList_RethinkDimensions()
1729 IPTR IconList__MUIM_IconList_RethinkDimensions(struct IClass *CLASS, Object *obj, struct MUIP_IconList_RethinkDimensions *message)
1731 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1733 struct IconEntry *entry = NULL;
1734 LONG maxx = 0,
1735 maxy = 0;
1736 struct Rectangle icon_rect;
1738 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
1739 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1740 #endif
1742 if (message->singleicon != NULL)
1744 entry = message->singleicon;
1745 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1747 maxy = data->icld_LVMAttribs->lmva_RowHeight;
1748 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
1750 maxy += data->icld_LVMAttribs->lmva_HeaderHeight;
1753 else
1755 maxx = data->icld_AreaWidth - 1,
1756 maxy = data->icld_AreaHeight - 1;
1759 #if defined(DEBUG_ILC_ICONPOSITIONING)
1760 D(bug("[IconList] %s: SingleIcon - maxx = %d, maxy = %d\n", __PRETTY_FUNCTION__, maxx, maxy));
1761 #endif
1763 else
1765 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1767 maxy = data->icld_LVMAttribs->lmva_RowHeight;
1768 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
1770 maxy += data->icld_LVMAttribs->lmva_HeaderHeight;
1773 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1776 while (entry != NULL)
1778 if (entry->ie_DiskObj &&
1779 (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1781 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1783 maxy += data->icld_LVMAttribs->lmva_RowHeight;
1785 else
1787 IconList_GetIconAreaRectangle(obj, data, entry, &icon_rect);
1789 icon_rect.MaxX += entry->ie_IconX + data->icld__Option_IconHorizontalSpacing;
1790 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1791 (entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
1792 icon_rect.MaxX += (data->icld_IconAreaLargestWidth - entry->ie_AreaWidth);
1794 icon_rect.MaxY += entry->ie_IconY + data->icld__Option_IconVerticalSpacing;
1796 if (icon_rect.MaxX > maxx) maxx = icon_rect.MaxX;
1797 if (icon_rect.MaxY > maxy) maxy = icon_rect.MaxY;
1801 if (message->singleicon)
1802 break;
1804 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
1807 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1809 int col;
1811 for(col = 0; col < NUM_COLUMNS; col++)
1813 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[col];
1815 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
1817 maxx += data->icld_LVMAttribs->lmva_ColumnWidth[index];
1821 /* update our view when max x/y have changed */
1822 if (maxx + 1 != data->icld_AreaWidth)
1824 data->icld_AreaWidth = maxx + 1;
1825 SET(obj, MUIA_IconList_Width, data->icld_AreaWidth);
1827 if (maxy + 1 != data->icld_AreaHeight)
1829 data->icld_AreaHeight = maxy + 1;
1830 SET(obj, MUIA_IconList_Height, data->icld_AreaHeight);
1833 return TRUE;
1837 * This function executes the layouting when AutoSort is enabled. This means all icons are layouted regardless if
1838 * they have Provided position or not.
1841 static VOID IconList_Layout_FullAutoLayout(struct IClass *CLASS, Object *obj)
1843 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1844 struct IconEntry *entry = NULL;
1845 struct IconEntry *pass_first = NULL; /* First entry of current column or row */
1847 LONG left = data->icld__Option_IconHorizontalSpacing;
1848 LONG top = data->icld__Option_IconVerticalSpacing;
1849 LONG cur_x = left;
1850 LONG cur_y = top;
1851 LONG gridx = 0;
1852 LONG gridy = 0;
1853 LONG maxw = 0; /* Widest & talest entry in a column or row */
1854 LONG maxh = 0;
1856 BOOL calcnextpos;
1857 struct Rectangle iconrect;
1859 /* Now go to the actual positioning */
1860 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1861 while (entry != NULL)
1863 calcnextpos = FALSE;
1864 if ((entry->ie_DiskObj != NULL) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1866 calcnextpos = TRUE;
1868 /* Set previously calculated position to this icon */
1869 entry->ie_IconX = cur_x;
1870 entry->ie_IconY = cur_y;
1872 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
1874 if (data->icld_SelectionLastClicked == NULL) data->icld_SelectionLastClicked = entry;
1875 if (data->icld_FocusIcon == NULL) data->icld_FocusIcon = entry;
1878 /* Calculate grid size to advanced the coordinate in next step */
1879 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1881 maxw = data->icld_IconAreaLargestWidth + data->icld__Option_IconHorizontalSpacing;
1882 maxh = data->icld_IconLargestHeight + data->icld__Option_IconImageSpacing + data->icld_LabelLargestHeight + data->icld__Option_IconVerticalSpacing;
1883 gridx = maxw;
1884 gridy = maxh;
1886 else
1888 if (!(pass_first)) pass_first = entry;
1890 IconList_GetIconAreaRectangle(obj, data, entry, &iconrect);
1892 if ((maxw < entry->ie_AreaWidth) || (maxh < entry->ie_AreaHeight))
1894 if (maxw < entry->ie_AreaWidth) maxw = entry->ie_AreaWidth;
1895 if (maxh < entry->ie_AreaHeight) maxh = entry->ie_AreaHeight;
1896 if (pass_first != entry)
1898 entry = pass_first;
1899 cur_x = entry->ie_IconX;
1900 cur_y = entry->ie_IconY;
1901 /* We detected that the new icon it taller/wider than icons so far in this row/column.
1902 * We need to re-layout this row/column. */
1903 continue;
1907 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1909 /* Centering */
1910 if (entry->ie_AreaWidth < maxw)
1911 entry->ie_IconX += ( maxw - entry->ie_AreaWidth ) / 2;
1913 gridx = maxw;
1914 gridy = entry->ie_AreaHeight + data->icld__Option_IconVerticalSpacing;
1916 else
1918 /* Centering */ /* Icons look better not centered in this case - disabled */
1919 /* if (entry->ie_AreaHeight < maxh)
1920 entry->ie_IconY += ( maxh - entry->ie_AreaHeight ) / 2; */
1922 gridx = entry->ie_AreaWidth + data->icld__Option_IconHorizontalSpacing;
1923 gridy = maxh;
1929 * Advance to next icon and calculate its position based on grid sizes from previous step.
1930 * Don't set position - it is done at beginning of the loop.
1932 if ((entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode)) != NULL)
1934 if (calcnextpos)
1936 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1938 cur_y += gridy;
1940 if ((cur_y >= data->icld_ViewHeight) ||
1941 ((data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH) && ((cur_y + entry->ie_AreaHeight - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight)) ||
1942 ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) && ((cur_y + data->icld_IconAreaLargestHeight - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight)))
1944 /* Wrap "around" if the icon would be below bottom border */
1945 cur_x += maxw;
1946 cur_y = top;
1947 pass_first = NULL;
1948 maxw = 0;
1951 else
1953 cur_x += gridx;
1955 if ((cur_x >= data->icld_ViewWidth) ||
1956 ((data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH) && ((cur_x + entry->ie_AreaWidth - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth)) ||
1957 ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) && ((cur_x + data->icld_IconAreaLargestWidth - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth)))
1959 /* Wrap "around" if the icon would be right of right border */
1960 cur_x = left;
1961 cur_y += maxh;
1962 pass_first = NULL;
1963 maxh = 0;
1971 static VOID IconList_Layout_PartialAutoLayout(struct IClass *CLASS, Object *obj)
1973 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1974 struct Region *occupied = NewRegion();
1975 struct IconEntry *entry = NULL;
1976 LONG left = data->icld__Option_IconHorizontalSpacing;
1977 LONG top = data->icld__Option_IconVerticalSpacing;
1978 LONG cur_x = left, cur_y = top;
1980 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1981 while (entry != NULL)
1983 if ((entry->ie_ProvidedIconX != NO_ICON_POSITION) && (entry->ie_ProvidedIconY != NO_ICON_POSITION)
1984 && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1986 struct Rectangle iconrect = {
1987 entry->ie_ProvidedIconX,
1988 entry->ie_ProvidedIconY,
1989 entry->ie_ProvidedIconX + entry->ie_AreaWidth - 1,
1990 entry->ie_ProvidedIconY + entry->ie_AreaHeight - 1
1993 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1994 iconrect.MaxY += data->icld__Option_IconVerticalSpacing;
1995 else
1996 iconrect.MaxX += data->icld__Option_IconHorizontalSpacing;
1998 D(bug("Adding %s (%d %d)(%d %d)\n", entry->ie_TxtBuf_DisplayedLabel,
1999 (LONG)iconrect.MinX, (LONG)iconrect.MinY, (LONG)iconrect.MaxX, (LONG)iconrect.MaxY));
2001 OrRectRegion(occupied, &iconrect);
2003 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
2006 /* Now go to the actual positioning */
2007 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
2008 while (entry != NULL)
2010 if ((entry->ie_DiskObj != NULL) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
2012 if ((entry->ie_ProvidedIconX != NO_ICON_POSITION) && (entry->ie_ProvidedIconY != NO_ICON_POSITION))
2014 entry->ie_IconX = entry->ie_ProvidedIconX;
2015 entry->ie_IconY = entry->ie_ProvidedIconY;
2017 else
2019 LONG gridx, gridy, stepx = 0, stepy = 0, addx = 0;
2020 struct Rectangle iconarea;
2021 BOOL first = TRUE;
2023 /* Calculate grid size and step */
2024 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
2026 gridx = data->icld_IconAreaLargestWidth + data->icld__Option_IconHorizontalSpacing;
2027 gridy = data->icld_IconLargestHeight + data->icld__Option_IconImageSpacing + data->icld_LabelLargestHeight + data->icld__Option_IconVerticalSpacing;
2029 else
2031 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
2033 gridx = data->icld_IconAreaLargestWidth; /* This gives better centering effect */
2034 gridy = entry->ie_AreaHeight + data->icld__Option_IconVerticalSpacing;
2035 addx = (gridx - entry->ie_AreaWidth) / 2;
2037 else
2039 gridx = entry->ie_AreaWidth + data->icld__Option_IconHorizontalSpacing;
2040 gridy = entry->ie_AreaHeight + data->icld__Option_IconVerticalSpacing;
2044 /* Find first not occupied spot matching the calculate rectangle */
2047 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
2049 /* Overwrite value set via RegionAndRect */
2050 stepx = gridx;
2051 stepy = gridy;
2054 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
2056 /* Advance to next position */
2057 if (!first) cur_y += stepy;
2059 if ((cur_y >= data->icld_ViewHeight) ||
2060 ((cur_y + gridy - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight))
2062 /* Wrap "around" if the icon would be below bottom border */
2063 cur_x += gridx;
2064 cur_y = top;
2067 else
2069 /* Advance to next position */
2070 if (!first) cur_x += stepx;
2072 if ((cur_x >= data->icld_ViewWidth) ||
2073 ((cur_x + gridx - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth))
2075 /* Wrap "around" if the icon would be right of right border */
2076 cur_x = left;
2077 cur_y += gridy;
2081 iconarea.MinX = cur_x;
2082 iconarea.MinY = cur_y;
2083 iconarea.MaxX = cur_x + gridx - 1;
2084 iconarea.MaxY = cur_y + gridy - 1;
2086 first = FALSE;
2088 } while(RegionAndRect(occupied, &iconarea, &stepx, &stepy));
2090 entry->ie_IconX = iconarea.MinX + addx;
2091 entry->ie_IconY = iconarea.MinY;
2093 /* Add this area to occupied list */
2094 OrRectRegion(occupied, &iconarea);
2096 /* Add spacing to next icon */
2097 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
2098 cur_y += gridy;
2099 else
2100 cur_x += gridx;
2104 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
2107 DisposeRegion(occupied);
2111 ///IconList__MUIM_IconList_PositionIcons()
2112 /**************************************************************************
2113 MUIM_PositionIcons - Place icons with NO_ICON_POSITION coords somewhere
2114 **************************************************************************/
2115 IPTR IconList__MUIM_IconList_PositionIcons(struct IClass *CLASS, Object *obj, struct MUIP_IconList_PositionIcons *message)
2117 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2118 struct IconEntry *entry = NULL;
2121 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
2122 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2123 #endif
2124 if ((data->icld_SortFlags & MUIV_IconList_Sort_AutoSort) == 0)
2126 IconList_Layout_PartialAutoLayout(CLASS, obj);
2128 else
2130 IconList_Layout_FullAutoLayout(CLASS, obj);
2134 * Set Provided icon position on all icons (this can't be done as part of previous loop!)
2135 * The icons will not no longer be autolayouted unless MUIV_IconList_Sort_AutoSort is set.
2136 * This give the stability that new icons appearing won't make existing icons jump from their places
2138 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
2139 while (entry != NULL)
2141 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
2142 DoMethod(obj, MUIM_IconList_PropagateEntryPos, entry);
2144 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
2148 DoMethod(obj, MUIM_IconList_RethinkDimensions, NULL);
2149 return (IPTR)NULL;
2153 ///OM_NEW()
2155 #define ICONENTRY_SIZE 16
2157 static inline void CalcHeight(struct ListViewModeAttribs *LVMAttribs, struct TextFont *LabelFont)
2159 ULONG YSize = LabelFont ? LabelFont->tf_YSize : 0;
2161 LVMAttribs->lmva_HeaderHeight = HEADERLINE_EXTRAHEIGHT + YSize;
2162 LVMAttribs->lmva_RowHeight = LINE_EXTRAHEIGHT + ((ICONENTRY_SIZE > YSize) ? ICONENTRY_SIZE : YSize);
2165 /**************************************************************************
2166 OM_NEW
2167 **************************************************************************/
2168 IPTR IconList__OM_NEW(struct IClass *CLASS, Object *obj, struct opSet *message)
2170 struct IconList_DATA *data = NULL;
2171 struct TextFont *icl_WindowFont = NULL;
2172 // struct RastPort *icl_RastPort = NULL;
2173 int i;
2175 #if defined(DEBUG_ILC_FUNCS)
2176 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2177 #endif
2179 icl_WindowFont = (struct TextFont *) GetTagData(MUIA_Font, (IPTR) NULL, message->ops_AttrList);
2181 obj = (Object *)DoSuperNewTags(CLASS, obj, NULL,
2182 MUIA_FillArea, FALSE,
2183 MUIA_Dropable, TRUE,
2184 MUIA_Font, MUIV_Font_Tiny,
2185 TAG_MORE, (IPTR) message->ops_AttrList);
2187 if (!obj) return FALSE;
2189 data = INST_DATA(CLASS, obj);
2191 data->icld_Pool = CreatePool(0,4096,4096);
2192 if (!data->icld_Pool)
2194 CoerceMethod(CLASS,obj,OM_DISPOSE);
2195 return (IPTR)NULL;
2198 #if defined(DEBUG_ILC_FUNCS)
2199 D(bug("[IconList] %s: SELF = 0x%p, muiRenderInfo = 0x%p\n", __PRETTY_FUNCTION__, obj, muiRenderInfo(obj)));
2200 #endif
2201 NewList((struct List*)&data->icld_IconList);
2202 NewList((struct List*)&data->icld_SelectionList);
2204 data->icld_IconLabelFont = icl_WindowFont;
2206 /* Setup List View-Mode options */
2207 if ((data->icld_LVMAttribs = AllocMem(sizeof(struct ListViewModeAttribs), MEMF_CLEAR)) != NULL)
2209 for(i = 0; i < NUM_COLUMNS; i++)
2211 data->icld_LVMAttribs->lmva_ColumnPos[i] = i;
2212 data->icld_LVMAttribs->lmva_ColumnFlags[i] = LVMCF_COLVISIBLE;
2213 data->icld_LVMAttribs->lmva_ColumnWidth[i] = 100;
2214 data->icld_LVMAttribs->lmva_ColumnHAlign[i] = COLUMN_ALIGN_LEFT;
2215 switch (i)
2217 case INDEX_TYPE:
2218 data->icld_LVMAttribs->lmva_ColumnHAlign[i] = COLUMN_ALIGN_RIGHT;
2219 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= (LVMCF_COLCLICKABLE|LVMCF_COLSORTABLE);
2220 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Type";
2221 data->icld_LVMAttribs->lmva_ColumnWidth[i] = ICONENTRY_SIZE + 2;
2222 break;
2224 case INDEX_NAME:
2225 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= (LVMCF_COLCLICKABLE|LVMCF_COLSORTABLE);
2226 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Name";
2227 break;
2229 case INDEX_SIZE:
2230 data->icld_LVMAttribs->lmva_ColumnHAlign[i] = COLUMN_ALIGN_RIGHT;
2231 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= LVMCF_COLSORTABLE;
2232 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Size";
2233 break;
2235 case INDEX_LASTACCESS:
2236 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= LVMCF_COLSORTABLE;
2237 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Last Accessed";
2238 break;
2240 case INDEX_COMMENT:
2241 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Comment";
2242 break;
2244 case INDEX_PROTECTION:
2245 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Protection";
2246 break;
2248 default:
2249 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "<Unknown>";
2250 break;
2253 data->icld_LVMAttribs->lmva_LastSelectedColumn = -1;
2254 data->icld_LVMAttribs->lmva_SortColumn = INDEX_NAME;
2255 data->icld_LVMAttribs->lvma_Flags = LVMAF_HEADERDRAWTOEND;
2257 * Seems to be not needed because it's done in MUIM_Setup. No rendering happens before it.
2258 * Height calculation moved to MUIM_Setup because font pointer can be NULL here (if user-specified
2259 * font failed to open). In this case we fail back to the font specified in MUI's AreaData, but
2260 * it becomes known only in MUIM_Setup
2262 CalcHeight(data->icld_LVMAttribs, data->icld_IconLabelFont); */
2265 /* Get/Set initial values */
2266 /* TODO: TrimVolumeNames should be prefs settable */
2267 data->icld__Option_TrimVolumeNames = TRUE;
2268 /* TODO: Adjust overlap by window border width */
2269 data->icld__Option_IconBorderOverlap = 10;
2271 data->icld__Option_IconListMode = (UBYTE)GetTagData(MUIA_IconList_IconListMode, 0, message->ops_AttrList);
2272 data->icld__Option_LabelTextMode = (UBYTE)GetTagData(MUIA_IconList_LabelText_Mode, 0, message->ops_AttrList);
2273 data->icld__Option_LabelTextMaxLen = (ULONG)GetTagData(MUIA_IconList_LabelText_MaxLineLen, ILC_ICONLABEL_MAXLINELEN_DEFAULT, message->ops_AttrList);
2274 data->icld__Option_DragImageTransparent = (BOOL)GetTagData(MUIA_IconList_DragImageTransparent, FALSE, message->ops_AttrList);
2276 if ( data->icld__Option_LabelTextMaxLen < ILC_ICONLABEL_SHORTEST )
2277 data->icld__Option_LabelTextMaxLen = ILC_ICONLABEL_MAXLINELEN_DEFAULT;
2279 data->icld__Option_LastLabelTextMaxLen = data->icld__Option_LabelTextMaxLen;
2281 #if defined(DEBUG_ILC_FUNCS)
2282 D(bug("[IconList] %s: MaxLineLen : %ld\n", __PRETTY_FUNCTION__, data->icld__Option_LabelTextMaxLen));
2283 #endif
2284 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_NEWSIZE | IDCMP_MENUVERIFY;
2285 data->ehn.ehn_Priority = 0;
2286 data->ehn.ehn_Flags = 0;
2287 data->ehn.ehn_Object = obj;
2288 data->ehn.ehn_Class = CLASS;
2290 data->icld_SortFlags = MUIV_IconList_Sort_ByName;
2291 data->icld_DisplayFlags = ICONLIST_DISP_SHOWINFO;
2293 __iconlist_UpdateLabels_hook.h_Entry = (HOOKFUNC)IconList__HookFunc_UpdateLabelsFunc;
2295 DoMethod
2297 obj, MUIM_Notify, MUIA_IconList_LabelText_MaxLineLen, MUIV_EveryTime,
2298 (IPTR)obj, 3,
2299 MUIM_CallHook, &__iconlist_UpdateLabels_hook, (IPTR)CLASS
2302 DoMethod
2304 obj, MUIM_Notify, MUIA_IconList_LabelText_MultiLine, MUIV_EveryTime,
2305 (IPTR)obj, 3,
2306 MUIM_CallHook, &__iconlist_UpdateLabels_hook, (IPTR)CLASS
2309 #if defined(DEBUG_ILC_FUNCS)
2310 D(bug("[IconList] obj = %ld\n", obj));
2311 #endif
2312 return (IPTR)obj;
2316 ///OM_DISPOSE()
2317 /**************************************************************************
2318 OM_DISPOSE
2319 **************************************************************************/
2320 IPTR IconList__OM_DISPOSE(struct IClass *CLASS, Object *obj, Msg message)
2322 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2323 struct IconEntry *node = NULL;
2325 #if defined(DEBUG_ILC_FUNCS)
2326 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2327 #endif
2329 #if defined(__AROS__)
2330 ForeachNode(&data->icld_IconList, node)
2331 #else
2332 Foreach_Node(&data->icld_IconList, node);
2333 #endif
2335 if (node->ie_DiskObj)
2336 FreeDiskObject(node->ie_DiskObj);
2339 if (data->icld_Pool) DeletePool(data->icld_Pool);
2341 DoSuperMethodA(CLASS,obj,message);
2342 return (IPTR)NULL;
2346 ///OM_SET()
2347 /**************************************************************************
2348 OM_SET
2349 **************************************************************************/
2350 IPTR IconList__OM_SET(struct IClass *CLASS, Object *obj, struct opSet *message)
2352 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2353 struct TagItem *tag = NULL,
2354 *tags = NULL;
2356 WORD oldleft = data->icld_ViewX,
2357 oldtop = data->icld_ViewY;
2358 //oldwidth = data->icld_ViewWidth,
2359 //oldheight = data->icld_ViewHeight;
2361 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ATTRIBS)
2362 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2363 #endif
2365 /* parse initial taglist */
2366 for (tags = message->ops_AttrList; (tag = NextTagItem((TAGITEM)&tags)); )
2368 switch (tag->ti_Tag)
2370 case MUIA_Virtgroup_Left:
2371 #if defined(DEBUG_ILC_ATTRIBS)
2372 D(bug("[IconList] %s: MUIA_Virtgroup_Left %ld\n", __PRETTY_FUNCTION__, tag->ti_Data));
2373 #endif
2374 if (data->icld_ViewX != tag->ti_Data)
2375 data->icld_ViewX = tag->ti_Data;
2376 break;
2378 case MUIA_Virtgroup_Top:
2379 #if defined(DEBUG_ILC_ATTRIBS)
2380 D(bug("[IconList] %s: MUIA_Virtgroup_Top %ld\n", __PRETTY_FUNCTION__, tag->ti_Data));
2381 #endif
2382 if (data->icld_ViewY != tag->ti_Data)
2383 data->icld_ViewY = tag->ti_Data;
2384 break;
2386 case MUIA_IconList_Rastport:
2387 #if defined(DEBUG_ILC_ATTRIBS)
2388 D(bug("[IconList] %s: MUIA_IconList_Rastport 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2389 #endif
2390 data->icld_DisplayRastPort = (struct RastPort*)tag->ti_Data;
2391 data->icld_DrawOffsetX = _mleft(obj);
2392 data->icld_DrawOffsetY = _mtop(obj);
2393 if (data->icld_BufferRastPort != NULL)
2395 //Buffer still set!?!?!
2397 SET(obj, MUIA_IconList_BufferRastport, tag->ti_Data);
2398 break;
2400 case MUIA_IconList_BufferRastport:
2401 #if defined(DEBUG_ILC_ATTRIBS)
2402 D(bug("[IconList] %s: MUIA_IconList_BufferRastport 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2403 #endif
2404 data->icld_BufferRastPort = (struct RastPort*)tag->ti_Data;
2405 break;
2407 case MUIA_Font:
2408 #if defined(DEBUG_ILC_ATTRIBS)
2409 D(bug("[IconList] %s: MUIA_Font 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2410 #endif
2411 data->icld_IconLabelFont = (struct TextFont*)tag->ti_Data;
2412 /* FIXME: Should we call CalcHeight() here because our font changed? */
2413 break;
2415 case MUIA_IconList_LabelInfoText_Font:
2416 #if defined(DEBUG_ILC_ATTRIBS)
2417 D(bug("[IconList] %s: MUIA_IconList_LabelInfoText_Font 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2418 #endif
2419 data->icld_IconInfoFont = (struct TextFont*)tag->ti_Data;
2420 break;
2422 case MUIA_IconList_DisplayFlags:
2424 #if defined(DEBUG_ILC_ATTRIBS)
2425 D(bug("[IconList] %s: MUIA_IconList_DisplayFlags %08x\n", __PRETTY_FUNCTION__, tag->ti_Data));
2426 #endif
2427 // ULONG origModeFlags = data->icld_DisplayFlags & (ICONLIST_DISP_MODEDEFAULT|ICONLIST_DISP_MODELABELRIGHT|ICONLIST_DISP_MODELIST);
2428 data->icld_DisplayFlags = (ULONG)tag->ti_Data;
2430 if (data->icld_DisplayFlags & ICONLIST_DISP_BUFFERED)
2432 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2433 D(bug("[IconList] %s: MUIA_IconList_DisplayFlags & ICONLIST_DISP_BUFFERED\n", __PRETTY_FUNCTION__));
2434 #endif
2435 if ((data->icld_BufferRastPort != NULL)
2436 && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
2438 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2439 D(bug("[IconList] %s: BackLayer @ %p for BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
2440 #endif
2441 if ((GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_WIDTH) != data->icld_ViewWidth)
2442 || (GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_HEIGHT) != data->icld_ViewHeight))
2444 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
2445 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2446 D(bug("[IconList] %s: Destroying old BackLayer\n", __PRETTY_FUNCTION__));
2447 #endif
2448 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2449 DeleteLayer(0, oldLayer);
2453 if ((data->icld_BufferRastPort == NULL) || (data->icld_BufferRastPort == data->icld_DisplayRastPort))
2455 struct BitMap *bitmap_New = NULL;
2456 ULONG tmp_RastDepth;
2457 struct Layer_Info *li = NULL;
2459 tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
2460 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
2461 data->icld_ViewHeight,
2462 tmp_RastDepth,
2463 BMF_CLEAR,
2464 data->icld_DisplayRastPort->BitMap))!=NULL)
2466 if ((data->icld_BufferRastPort = CreateRastPort())!=NULL)
2468 data->icld_BufferRastPort->BitMap = bitmap_New;
2469 if ((li = NewLayerInfo()))
2471 if ((data->icld_BufferRastPort->Layer = CreateUpfrontLayer(li, data->icld_BufferRastPort->BitMap, 0, 0, data->icld_ViewWidth - 1, data->icld_ViewHeight - 1, 0, NULL)))
2474 * Mark it as a buffered rastport.
2477 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2478 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
2479 #endif
2480 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
2481 data->icld_DrawOffsetX = 0;
2482 data->icld_DrawOffsetY = 0;
2484 else
2485 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2487 else
2488 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2490 else
2491 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2493 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
2495 if (bitmap_New) FreeBitMap(bitmap_New);
2496 if (li) DisposeLayerInfo(li);
2497 data->icld_DrawOffsetX = _mleft(obj);
2498 data->icld_DrawOffsetY = _mtop(obj);
2502 else
2504 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
2506 //Free up the buffers layer, rastport and bitmap since they are no longer needed ..
2507 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
2508 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2509 InstallClipRegion(oldLayer, NULL);
2510 DeleteLayer(0, oldLayer);
2511 FreeBitMap(data->icld_BufferRastPort->BitMap);
2512 data->icld_DrawOffsetX = _mleft(obj);
2513 data->icld_DrawOffsetY = _mtop(obj);
2516 SET(obj, MUIA_IconList_Changed, TRUE);
2518 break;
2520 case MUIA_IconList_SortFlags:
2521 #if defined(DEBUG_ILC_ATTRIBS)
2522 D(bug("[IconList] %s: MUIA_IconList_SortFlags %08x\n", __PRETTY_FUNCTION__, tag->ti_Data));
2523 #endif
2524 data->icld_SortFlags = (ULONG)tag->ti_Data;
2525 break;
2527 case MUIA_IconList_DragImageTransparent:
2528 data->icld__Option_DragImageTransparent = (BOOL)tag->ti_Data;
2529 break;
2531 case MUIA_IconList_IconListMode:
2532 #if defined(DEBUG_ILC_ATTRIBS)
2533 D(bug("[IconList] %s: MUIA_IconList_IconListMode %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2534 #endif
2535 data->icld__Option_IconListMode = (UBYTE)tag->ti_Data;
2536 break;
2538 case MUIA_IconList_LabelText_Mode:
2539 #if defined(DEBUG_ILC_ATTRIBS)
2540 D(bug("[IconList] %s: MUIA_IconList_LabelText_Mode %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2541 #endif
2542 data->icld__Option_LabelTextMode = (UBYTE)tag->ti_Data;
2543 break;
2545 case MUIA_IconList_LabelText_MaxLineLen:
2546 #if defined(DEBUG_ILC_ATTRIBS)
2547 D(bug("[IconList] %s: MUIA_IconList_LabelText_MaxLineLen %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2548 #endif
2549 if (tag->ti_Data >= ILC_ICONLABEL_SHORTEST)
2551 data->icld__Option_LabelTextMaxLen = (ULONG)tag->ti_Data;
2553 else
2555 data->icld__Option_LabelTextMaxLen = ILC_ICONLABEL_MAXLINELEN_DEFAULT;
2557 break;
2559 case MUIA_IconList_LabelText_MultiLine:
2560 #if defined(DEBUG_ILC_ATTRIBS)
2561 D(bug("[IconList] %s: MUIA_IconList_LabelText_MultiLine %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2562 #endif
2563 data->icld__Option_LabelTextMultiLine = (ULONG)tag->ti_Data;
2564 if (data->icld__Option_LabelTextMultiLine == 0)data->icld__Option_LabelTextMultiLine = 1;
2565 break;
2567 case MUIA_IconList_LabelText_MultiLineOnFocus:
2568 #if defined(DEBUG_ILC_ATTRIBS)
2569 D(bug("[IconList] %s: MUIA_IconList_LabelText_MultiLineOnFocus %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2570 #endif
2571 data->icld__Option_LabelTextMultiLineOnFocus = (BOOL)tag->ti_Data;
2572 break;
2574 case MUIA_IconList_Icon_HorizontalSpacing:
2575 #if defined(DEBUG_ILC_ATTRIBS)
2576 D(bug("[IconList] %s: MUIA_IconList_Icon_HorizontalSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2577 #endif
2578 data->icld__Option_IconHorizontalSpacing = (UBYTE)tag->ti_Data;
2579 break;
2581 case MUIA_IconList_Icon_VerticalSpacing:
2582 #if defined(DEBUG_ILC_ATTRIBS)
2583 D(bug("[IconList] %s: MUIA_IconList_Icon_VerticalSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2584 #endif
2585 data->icld__Option_IconVerticalSpacing = (UBYTE)tag->ti_Data;
2586 break;
2588 case MUIA_IconList_Icon_ImageSpacing:
2589 #if defined(DEBUG_ILC_ATTRIBS)
2590 D(bug("[IconList] %s: MUIA_IconList_Icon_ImageSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2591 #endif
2592 data->icld__Option_IconImageSpacing = (UBYTE)tag->ti_Data;
2593 break;
2595 case MUIA_IconList_LabelText_HorizontalPadding:
2596 #if defined(DEBUG_ILC_ATTRIBS)
2597 D(bug("[IconList] %s: MUIA_IconList_LabelText_HorizontalPadding %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2598 #endif
2599 data->icld__Option_LabelTextHorizontalPadding = (UBYTE)tag->ti_Data;
2600 break;
2602 case MUIA_IconList_LabelText_VerticalPadding:
2603 #if defined(DEBUG_ILC_ATTRIBS)
2604 D(bug("[IconList] %s: MUIA_IconList_LabelText_VerticalPadding %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2605 #endif
2606 data->icld__Option_LabelTextVerticalPadding = (UBYTE)tag->ti_Data;
2607 break;
2609 case MUIA_IconList_LabelText_BorderWidth:
2610 #if defined(DEBUG_ILC_ATTRIBS)
2611 D(bug("[IconList] %s: MUIA_IconList_LabelText_BorderWidth %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2612 #endif
2613 data->icld__Option_LabelTextBorderWidth = (UBYTE)tag->ti_Data;
2614 break;
2616 case MUIA_IconList_LabelText_BorderHeight:
2617 #if defined(DEBUG_ILC_ATTRIBS)
2618 D(bug("[IconList] %s: MUIA_IconList_LabelText_BorderHeight %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2619 #endif
2620 data->icld__Option_LabelTextBorderHeight = (UBYTE)tag->ti_Data;
2621 break;
2623 case MUIA_IconList_LabelText_Pen:
2624 data->icld_LabelPen = (ULONG)tag->ti_Data;
2625 break;
2627 case MUIA_IconList_LabelText_ShadowPen:
2628 data->icld_LabelShadowPen = (ULONG)tag->ti_Data;
2629 break;
2631 case MUIA_IconList_LabelInfoText_Pen:
2632 data->icld_InfoPen = (ULONG)tag->ti_Data;
2633 break;
2635 case MUIA_IconList_LabelInfoText_ShadowPen:
2636 data->icld_InfoShadowPen = (ULONG)tag->ti_Data;
2637 break;
2639 /* Settings defined by the view class */
2640 case MUIA_IconListview_FixedBackground:
2641 #if defined(DEBUG_ILC_ATTRIBS)
2642 D(bug("[IconList] %s: MUIA_IconListview_FixedBackground\n", __PRETTY_FUNCTION__));
2643 #endif
2644 data->icld__Option_IconListFixedBackground = (BOOL)tag->ti_Data;
2645 break;
2647 case MUIA_IconListview_ScaledBackground:
2648 #if defined(DEBUG_ILC_ATTRIBS)
2649 D(bug("[IconList] %s: MUIA_IconListview_ScaledBackground\n", __PRETTY_FUNCTION__));
2650 #endif
2651 data->icld__Option_IconListScaledBackground = (BOOL)tag->ti_Data;
2652 break;
2654 /* We listen for MUIA_Background and set default values for known types */
2655 case MUIA_Background:
2656 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2657 D(bug("[IconList] %s: MUIA_Background\n", __PRETTY_FUNCTION__));
2658 #endif
2660 char *bgmode_string = (char *)tag->ti_Data;
2661 BYTE this_mode = bgmode_string[0] - 48;
2663 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2664 D(bug("[IconList] %s: MUIA_Background | MUI BG Mode = %d\n", __PRETTY_FUNCTION__, this_mode));
2665 #endif
2666 switch (this_mode)
2668 case 0:
2669 //MUI Pattern
2670 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2671 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2672 break;
2673 case 2:
2674 //MUI RGB color
2675 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2676 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2677 break;
2678 case 7:
2679 //Zune Gradient
2680 NNSET(obj, MUIA_IconListview_FixedBackground, TRUE);
2681 NNSET(obj, MUIA_IconListview_ScaledBackground, TRUE);
2682 break;
2683 case 5:
2684 //Image
2685 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2686 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2687 break;
2690 break;
2691 case MUIA_IconList_IconsDropped:
2692 data->icld_DragDropEvent = (struct IconList_Drop_Event *)tag->ti_Data;
2693 break;
2697 #if defined(DEBUG_ILC_ATTRIBS)
2698 D(bug("[IconList] %s(), out of switch\n", __PRETTY_FUNCTION__));
2699 #endif
2700 if ((oldleft != data->icld_ViewX) || (oldtop != data->icld_ViewY))
2702 data->icld_UpdateMode = UPDATE_SCROLL;
2703 data->update_scrolldx = data->icld_ViewX - oldleft;
2704 data->update_scrolldy = data->icld_ViewY - oldtop;
2705 #if defined(DEBUG_ILC_ATTRIBS)
2706 D(bug("[IconList] %s(), call MUI_Redraw()\n", __PRETTY_FUNCTION__));
2707 #endif
2708 MUI_Redraw(obj, MADF_DRAWUPDATE);
2711 #if defined(DEBUG_ILC_ATTRIBS)
2712 D(bug("[IconList] %s(), call DoSuperMethodA()\n", __PRETTY_FUNCTION__));
2713 #endif
2714 return DoSuperMethodA(CLASS, obj, (Msg)message);
2718 ///OM_GET()
2719 /**************************************************************************
2720 OM_GET
2721 **************************************************************************/
2722 IPTR IconList__OM_GET(struct IClass *CLASS, Object *obj, struct opGet *message)
2724 /* small macro to simplify return value storage */
2725 #define STORE *(message->opg_Storage)
2726 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2728 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ATTRIBS)
2729 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2730 #endif
2732 switch (message->opg_AttrID)
2734 case MUIA_IconList_Rastport: STORE = (IPTR)data->icld_DisplayRastPort; return 1;
2735 case MUIA_IconList_BufferRastport: STORE = (IPTR)data->icld_BufferRastPort; return 1;
2736 case MUIA_IconList_BufferLeft: STORE = (IPTR)data->icld_DrawOffsetX; return 1;
2737 case MUIA_IconList_BufferTop: STORE = (IPTR)data->icld_DrawOffsetY; return 1;
2738 case MUIA_IconList_BufferWidth:
2739 case MUIA_IconList_Width: STORE = (IPTR)data->icld_AreaWidth; return 1;
2740 case MUIA_IconList_BufferHeight:
2741 case MUIA_IconList_Height: STORE = (IPTR)data->icld_AreaHeight; return 1;
2742 case MUIA_IconList_IconsDropped: STORE = (IPTR)data->icld_DragDropEvent; return 1;
2743 case MUIA_IconList_Clicked: STORE = (IPTR)&data->icld_ClickEvent; return 1;
2744 case MUIA_IconList_IconListMode: STORE = (IPTR)data->icld__Option_IconListMode; return 1;
2745 case MUIA_IconList_LabelText_Mode: STORE = (IPTR)data->icld__Option_LabelTextMode; return 1;
2746 case MUIA_IconList_LabelText_MaxLineLen: STORE = (IPTR)data->icld__Option_LabelTextMaxLen; return 1;
2747 case MUIA_IconList_LabelText_MultiLine: STORE = (IPTR)data->icld__Option_LabelTextMultiLine; return 1;
2748 case MUIA_IconList_LabelText_MultiLineOnFocus: STORE = (IPTR)data->icld__Option_LabelTextMultiLineOnFocus; return 1;
2749 case MUIA_IconList_DisplayFlags: STORE = (IPTR)data->icld_DisplayFlags; return 1;
2750 case MUIA_IconList_SortFlags: STORE = (IPTR)data->icld_SortFlags; return 1;
2752 case MUIA_IconList_FocusIcon: STORE = (IPTR)data->icld_FocusIcon; return 1;
2754 case MUIA_Font: STORE = (IPTR)data->icld_IconLabelFont; return 1;
2755 case MUIA_IconList_LabelText_Pen: STORE = (IPTR)data->icld_LabelPen; return 1;
2756 case MUIA_IconList_LabelText_ShadowPen: STORE = (IPTR)data->icld_LabelShadowPen; return 1;
2757 case MUIA_IconList_LabelInfoText_Font: STORE = (IPTR)data->icld_IconInfoFont; return 1;
2758 case MUIA_IconList_LabelInfoText_Pen: STORE = (IPTR)data->icld_InfoPen; return 1;
2759 case MUIA_IconList_LabelInfoText_ShadowPen: STORE = (IPTR)data->icld_InfoShadowPen; return 1;
2760 case MUIA_IconList_DragImageTransparent: STORE = (IPTR)data->icld__Option_DragImageTransparent; return 1;
2762 case MUIA_IconList_Icon_HorizontalSpacing: STORE = (IPTR)data->icld__Option_IconHorizontalSpacing; return 1;
2763 case MUIA_IconList_Icon_VerticalSpacing: STORE = (IPTR)data->icld__Option_IconVerticalSpacing; return 1;
2764 case MUIA_IconList_Icon_ImageSpacing: STORE = (IPTR)data->icld__Option_IconImageSpacing; return 1;
2765 case MUIA_IconList_LabelText_HorizontalPadding: STORE = (IPTR)data->icld__Option_LabelTextHorizontalPadding; return 1;
2766 case MUIA_IconList_LabelText_VerticalPadding: STORE = (IPTR)data->icld__Option_LabelTextVerticalPadding; return 1;
2767 case MUIA_IconList_LabelText_BorderWidth: STORE = (IPTR)data->icld__Option_LabelTextBorderWidth; return 1;
2768 case MUIA_IconList_LabelText_BorderHeight: STORE = (IPTR)data->icld__Option_LabelTextBorderHeight; return 1;
2770 /* Settings defined by the view class */
2771 case MUIA_IconListview_FixedBackground: STORE = (IPTR)data->icld__Option_IconListFixedBackground; return 1;
2772 case MUIA_IconListview_ScaledBackground: STORE = (IPTR)data->icld__Option_IconListScaledBackground; return 1;
2774 /* ICON obj Changes */
2775 case MUIA_Virtgroup_Left: STORE = (IPTR)data->icld_ViewX; return 1;
2776 case MUIA_Virtgroup_Top: STORE = (IPTR)data->icld_ViewY; return 1;
2777 case MUIA_Family_List: STORE = (IPTR)&(data->icld_IconList); return 1; /* Get our list object */
2779 /* TODO: Get the version/revision from our config.. */
2780 case MUIA_Version: STORE = (IPTR)1; return 1;
2781 case MUIA_Revision: STORE = (IPTR)7; return 1;
2784 return DoSuperMethodA(CLASS, obj, (Msg) message);
2785 #undef STORE
2789 IPTR IconList__MUIM_Family_AddHead(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddHead *message)
2791 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2792 #if defined(DEBUG_ILC_FUNCS)
2793 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2794 #endif
2796 if (message->obj)
2798 /* TODO: Use the correct _OBJECT() code when we switch to icon.mui */
2799 // AddHead(&(data->icld_IconList), (struct Node *)_OBJECT(message->obj));
2800 AddHead(&(data->icld_IconList), (struct Node *)message->obj);
2801 return TRUE;
2803 else
2804 return FALSE;
2807 IPTR IconList__MUIM_Family_AddTail(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddTail *message)
2809 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2810 #if defined(DEBUG_ILC_FUNCS)
2811 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2812 #endif
2814 D(bug("[IconList] %s: list @ 0x%p, entry @ 0x%p '%s'\n", __PRETTY_FUNCTION__, &(data->icld_IconList), message->obj, ((struct IconEntry *)message->obj)->ie_IconNode.ln_Name));
2816 if (message->obj)
2818 /* TODO: Use the correct _OBJECT() code when we switch to icon.mui */
2819 // AddTail(&(data->icld_IconList), (struct Node *)_OBJECT(message->obj));
2820 AddTail(&(data->icld_IconList), (struct Node *)message->obj);
2821 return TRUE;
2823 else
2824 return FALSE;
2826 return (IPTR)NULL;
2828 #if !defined(WANDERER_BUILTIN_ICONLIST)
2829 IPTR IconList__OM_ADDMEMBER(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddTail *message)
2831 return IconList__MUIM_Family_AddTail(CLASS, obj, message);
2833 #endif
2835 IPTR IconList__MUIM_Family_Remove(struct IClass *CLASS, Object *obj, struct MUIP_Family_Remove *message)
2837 // struct IconList_DATA *data = INST_DATA(CLASS, obj);
2838 #if defined(DEBUG_ILC_FUNCS)
2839 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2840 #endif
2842 D(bug("[IconList] %s: entry @ 0x%p '%s'\n", __PRETTY_FUNCTION__, message->obj, ((struct IconEntry *)message->obj)->ie_IconNode.ln_Name));
2844 if (message->obj)
2846 /* TODO: Use the correct _OBJECT() code when we switch to icon.mui */
2847 // Remove((struct Node *)_OBJECT(message->obj));
2848 Remove((struct Node *)message->obj);
2849 return TRUE;
2851 else
2852 return FALSE;
2854 return (IPTR)NULL;
2856 #if !defined(WANDERER_BUILTIN_ICONLIST)
2857 IPTR IconList__OM_REMMEMBER(struct IClass *CLASS, Object *obj, struct MUIP_Family_Remove *message)
2859 return IconList__MUIM_Family_Remove(CLASS, obj, message);
2861 #endif
2863 ///MUIM_Setup()
2864 /**************************************************************************
2865 MUIM_Setup
2866 **************************************************************************/
2867 IPTR IconList__MUIM_Setup(struct IClass *CLASS, Object *obj, struct MUIP_Setup *message)
2869 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2870 struct IconEntry *node = NULL;
2871 IPTR geticon_error = 0, iconlistScreen;
2873 #if defined(DEBUG_ILC_FUNCS)
2874 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2875 #endif
2877 if (!DoSuperMethodA(CLASS, obj, (Msg) message)) return (IPTR)NULL;
2879 iconlistScreen = (IPTR)_screen(obj);
2880 #if defined(DEBUG_ILC_ICONRENDERING)
2881 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
2882 #endif
2884 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
2886 /* Get Internal Objects to use if not set .. */
2887 data->icld_DisplayRastPort = NULL;
2888 data->icld_BufferRastPort = NULL;
2890 if (data->icld_IconLabelFont == NULL) data->icld_IconLabelFont = _font(obj);
2891 if (data->icld_IconInfoFont == NULL) data->icld_IconInfoFont = data->icld_IconLabelFont;
2894 * Here we have our font, either from user preferences or from MUI's AreaData.
2895 * It's right time to set up some sizes.
2897 if (data->icld_LVMAttribs)
2898 CalcHeight(data->icld_LVMAttribs, data->icld_IconLabelFont);
2899 #if defined(DEBUG_ILC_ICONRENDERING)
2900 D(bug("[IconList] %s: Use Font @ 0x%p, RastPort @ 0x%p\n", __PRETTY_FUNCTION__, data->icld_IconLabelFont, data->icld_BufferRastPort ));
2901 #endif
2903 /* Set our base options .. */
2904 data->icld_LabelPen = _pens(obj)[MPEN_SHINE];
2905 data->icld_LabelShadowPen = _pens(obj)[MPEN_SHADOW];
2906 data->icld_InfoPen = _pens(obj)[MPEN_SHINE];
2907 data->icld_InfoShadowPen = _pens(obj)[MPEN_SHADOW];
2909 data->icld__Option_LabelTextMultiLine = 1;
2910 data->icld__Option_LastLabelTextMultiLine = data->icld__Option_LabelTextMultiLine;
2912 data->icld__Option_LabelTextMultiLineOnFocus = FALSE;
2914 data->icld__Option_IconHorizontalSpacing = ILC_ICON_HORIZONTALMARGIN_DEFAULT;
2915 data->icld__Option_IconVerticalSpacing = ILC_ICON_VERTICALMARGIN_DEFAULT;
2916 data->icld__Option_IconImageSpacing = ILC_ICONLABEL_IMAGEMARGIN_DEFAULT;
2917 data->icld__Option_LabelTextHorizontalPadding = ILC_ICONLABEL_HORIZONTALTEXTMARGIN_DEFAULT;
2918 data->icld__Option_LabelTextVerticalPadding = ILC_ICONLABEL_VERTICALTEXTMARGIN_DEFAULT;
2919 data->icld__Option_LabelTextBorderWidth = ILC_ICONLABEL_BORDERWIDTH_DEFAULT;
2920 data->icld__Option_LabelTextBorderHeight = ILC_ICONLABEL_BORDERHEIGHT_DEFAULT;
2922 if (data->icld_LVMAttribs)
2924 data->icld_LVMAttribs->lvma_IconDrawer = GetIconTags
2926 "WANDERER:Icons/drawer",
2927 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
2928 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
2929 ICONGETA_FailIfUnavailable, TRUE,
2930 ICONGETA_GenerateImageMasks, TRUE,
2931 ICONA_ErrorCode, &geticon_error,
2932 TAG_DONE
2935 #if defined(DEBUG_ILC_ICONRENDERING)
2936 if (data->icld_LVMAttribs->lvma_IconDrawer == NULL)
2938 D(bug("[IconList] %s: Couldnt get drawer DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
2940 #endif
2941 data->icld_LVMAttribs->lvma_IconFile = GetIconTags
2943 "WANDERER:Icons/file",
2944 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
2945 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
2946 ICONGETA_FailIfUnavailable, TRUE,
2947 ICONGETA_GenerateImageMasks, TRUE,
2948 ICONA_ErrorCode, &geticon_error,
2949 TAG_DONE
2952 #if defined(DEBUG_ILC_ICONRENDERING)
2953 if (data->icld_LVMAttribs->lvma_IconFile == NULL)
2955 D(bug("[IconList] %s: Couldnt get file DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
2957 #endif
2960 #if defined(__AROS__)
2961 ForeachNode(&data->icld_IconList, node)
2962 #else
2963 Foreach_Node(&data->icld_IconList, node);
2964 #endif
2966 if (!node->ie_DiskObj)
2968 if (!(node->ie_DiskObj = GetIconTags(node->ie_IconNode.ln_Name,
2969 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
2970 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
2971 ICONGETA_GenerateImageMasks, TRUE,
2972 ICONGETA_FailIfUnavailable, FALSE,
2973 ICONA_ErrorCode, &geticon_error,
2974 TAG_DONE)))
2976 #if defined(DEBUG_ILC_ICONRENDERING)
2977 D(bug("[IconList] %s: Failed to obtain Entry '%s's diskobj! (error code = 0x%p)\n", __PRETTY_FUNCTION__, node->ie_IconNode.ln_Name, geticon_error));
2978 #endif
2979 /* We should probably remove this node if the entry cant be obtained ? */
2983 return 1;
2987 ///MUIM_Show()
2988 /**************************************************************************
2989 MUIM_Show
2990 **************************************************************************/
2991 IPTR IconList__MUIM_Show(struct IClass *CLASS, Object *obj, struct MUIP_Show *message)
2993 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2994 LONG newleft,
2995 newtop;
2996 IPTR rc;
2998 #if defined(DEBUG_ILC_FUNCS)
2999 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3000 #endif
3002 if ((rc = DoSuperMethodA(CLASS, obj, (Msg)message)))
3004 newleft = data->icld_ViewX;
3005 newtop = data->icld_ViewY;
3007 if (newleft + _mwidth(obj) > data->icld_AreaWidth)
3008 newleft = data->icld_AreaWidth - _mwidth(obj);
3009 if (newleft < 0)
3010 newleft = 0;
3012 if (newtop + _mheight(obj) > data->icld_AreaHeight)
3013 newtop = data->icld_AreaHeight - _mheight(obj);
3014 if (newtop < 0)
3015 newtop = 0;
3017 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
3019 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
3020 MUIA_Virtgroup_Top, newtop,
3021 TAG_DONE);
3024 /* Get Internal Objects to use if not set .. */
3025 if (data->icld_DisplayRastPort == NULL)
3027 if (_rp(obj) != NULL)
3029 data->icld_DisplayRastPort = CloneRastPort(_rp(obj));
3031 #if defined(DEBUG_ILC_ICONRENDERING)
3032 else
3034 D(bug("[IconList] IconList__MUIM_Show: ERROR - NULL RastPort!\n"));
3036 #endif
3039 if (data->icld_DisplayFlags & ICONLIST_DISP_BUFFERED)
3041 struct BitMap *bitmap_New = NULL;
3042 struct Layer_Info *li = NULL;
3044 ULONG tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
3045 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
3046 data->icld_ViewHeight,
3047 tmp_RastDepth,
3048 BMF_CLEAR,
3049 data->icld_DisplayRastPort->BitMap))!=NULL)
3051 if ((data->icld_BufferRastPort = CreateRastPort())!=NULL)
3053 data->icld_BufferRastPort->BitMap = bitmap_New;
3054 if ((li = NewLayerInfo()))
3056 if ((data->icld_BufferRastPort->Layer = CreateUpfrontLayer(li, data->icld_BufferRastPort->BitMap, 0, 0, data->icld_ViewWidth - 1, data->icld_ViewHeight - 1, 0, NULL)))
3059 * Mark it as a buffered rastport.
3062 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
3063 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
3064 #endif
3065 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
3066 data->icld_DrawOffsetX = 0;
3067 data->icld_DrawOffsetY = 0;
3069 else
3070 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3072 else
3073 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3075 else
3076 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3078 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
3080 if (bitmap_New) FreeBitMap(bitmap_New);
3081 if (li) DisposeLayerInfo(li);
3082 data->icld_DrawOffsetX = _mleft(obj);
3083 data->icld_DrawOffsetY = _mtop(obj);
3086 else
3088 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3089 data->icld_DrawOffsetX = _mleft(obj);
3090 data->icld_DrawOffsetY = _mtop(obj);
3093 if (data->icld_IconLabelFont == NULL) data->icld_IconLabelFont = _font(obj);
3094 if (data->icld_IconInfoFont == NULL) data->icld_IconInfoFont = data->icld_IconLabelFont;
3095 #if defined(DEBUG_ILC_ICONRENDERING)
3096 D(bug("[IconList] IconList__MUIM_Show: Use Font @ 0x%p, RastPort @ 0x%p\n", data->icld_IconLabelFont, data->icld_BufferRastPort ));
3097 #endif
3099 if ((data->icld_BufferRastPort) && (data->icld_IconLabelFont))
3100 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
3102 return rc;
3106 ///MUIM_Hide()
3107 /**************************************************************************
3108 MUIM_Hide
3109 **************************************************************************/
3110 IPTR IconList__MUIM_Hide(struct IClass *CLASS, Object *obj, struct MUIP_Hide *message)
3112 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3113 IPTR rc;
3115 #if defined(DEBUG_ILC_FUNCS)
3116 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3117 #endif
3119 if ((rc = DoSuperMethodA(CLASS, obj, (Msg)message)))
3121 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
3123 DeleteLayer(0, data->icld_BufferRastPort->Layer);
3126 data->icld_BufferRastPort = NULL;
3128 if (data->icld_DisplayRastPort)
3129 FreeRastPort(data->icld_DisplayRastPort);
3131 data->icld_DisplayRastPort = NULL;
3133 return rc;
3137 ///MUIM_Cleanup()
3138 /**************************************************************************
3139 MUIM_Cleanup
3140 **************************************************************************/
3141 IPTR IconList__MUIM_Cleanup(struct IClass *CLASS, Object *obj, struct MUIP_Cleanup *message)
3143 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3144 struct IconEntry *node = NULL;
3146 #if defined(DEBUG_ILC_FUNCS)
3147 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3148 #endif
3150 #if defined(__AROS__)
3151 ForeachNode(&data->icld_IconList, node)
3152 #else
3153 Foreach_Node(&data->icld_IconList, node);
3154 #endif
3156 if (node->ie_DiskObj)
3158 FreeDiskObject(node->ie_DiskObj);
3159 node->ie_DiskObj = NULL;
3163 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
3165 return DoSuperMethodA(CLASS, obj, (Msg)message);
3169 ///MUIM_AskMinMax()
3170 /**************************************************************************
3171 MUIM_AskMinMax
3172 **************************************************************************/
3173 IPTR IconList__MUIM_AskMinMax(struct IClass *CLASS, Object *obj, struct MUIP_AskMinMax *message)
3175 ULONG rc = DoSuperMethodA(CLASS, obj, (Msg) message);
3177 #if defined(DEBUG_ILC_FUNCS)
3178 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3179 #endif
3181 message->MinMaxInfo->MinWidth += 96;
3182 message->MinMaxInfo->MinHeight += 64;
3184 message->MinMaxInfo->DefWidth += 200;
3185 message->MinMaxInfo->DefHeight += 180;
3187 message->MinMaxInfo->MaxWidth = MUI_MAXMAX;
3188 message->MinMaxInfo->MaxHeight = MUI_MAXMAX;
3190 return rc;
3194 ///MUIM_Layout()
3195 /**************************************************************************
3196 MUIM_Layout
3197 **************************************************************************/
3198 IPTR IconList__MUIM_Layout(struct IClass *CLASS, Object *obj,struct MUIP_Layout *message)
3200 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3201 ULONG rc;
3203 #if defined(DEBUG_ILC_FUNCS)
3204 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3205 #endif
3207 rc = DoSuperMethodA(CLASS, obj, (Msg)message);
3209 data->icld_ViewWidth = _mwidth(obj);
3210 data->icld_ViewHeight = _mheight(obj);
3212 return rc;
3216 static LONG FirstVisibleLine(struct IconList_DATA *data)
3218 return data->icld_ViewY / data->icld_LVMAttribs->lmva_RowHeight;
3221 static LONG NumVisibleLines(struct IconList_DATA *data)
3223 LONG visible = data->icld_ViewHeight + data->icld_LVMAttribs->lmva_RowHeight - 1 +
3224 (data->icld_ViewY % data->icld_LVMAttribs->lmva_RowHeight);
3226 visible /= data->icld_LVMAttribs->lmva_RowHeight;
3228 return visible;
3231 static void RenderListViewModeHeaderField(Object *obj, struct IconList_DATA *data,
3232 struct Rectangle *rect, LONG index, BOOL sel)
3234 IPTR penFill, penText, penDark, penBright;
3235 struct Rectangle rendRect;
3236 STRPTR text;
3237 struct TextExtent te;
3238 ULONG fit;
3240 if (sel == TRUE)
3242 penFill = _pens(obj)[MPEN_HALFSHADOW];
3243 penBright = _pens(obj)[MPEN_SHADOW];
3244 penDark = _pens(obj)[MPEN_HALFSHINE];
3246 else
3248 penFill = _pens(obj)[MPEN_HALFSHINE];
3249 penBright = _pens(obj)[MPEN_SHINE];
3250 penDark = _pens(obj)[MPEN_HALFSHADOW];
3252 penText = _pens(obj)[MPEN_TEXT];
3254 rendRect.MinX = rect->MinX;
3255 rendRect.MaxX = rect->MaxX;
3256 rendRect.MinY = rect->MinY;
3257 rendRect.MaxY = rect->MaxY;
3259 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3261 rendRect.MinX -= _mleft(obj);
3262 rendRect.MaxX -= _mleft(obj);
3263 rendRect.MinY -= _mtop(obj);
3264 rendRect.MaxY -= _mtop(obj);
3267 #if defined(DEBUG_ILC_FUNCS)
3268 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
3269 #endif
3271 if (((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0) && (index < NUM_COLUMNS))
3273 text = data->icld_LVMAttribs->lmva_ColumnTitle[index];
3275 SetAPen(data->icld_BufferRastPort, penFill); /* Background */
3276 RectFill(data->icld_BufferRastPort, rendRect.MinX + 1, rendRect.MinY + 1,
3277 rendRect.MaxX - 1, rendRect.MaxY - 1);
3279 SetAPen(data->icld_BufferRastPort, penBright); /* Top/Left */
3280 RectFill(data->icld_BufferRastPort, rendRect.MinX, rendRect.MinY, rendRect.MinX, rendRect.MaxY);
3281 RectFill(data->icld_BufferRastPort, rendRect.MinX + 1, rendRect.MinY, rendRect.MaxX - 1, rendRect.MinY);
3283 SetAPen(data->icld_BufferRastPort,penDark); /* Bottom/Right */
3284 RectFill(data->icld_BufferRastPort, rendRect.MaxX, rendRect.MinY, rendRect.MaxX, rendRect.MaxY);
3285 RectFill(data->icld_BufferRastPort, rendRect.MinX + 1, rendRect.MaxY, rendRect.MaxX - 1, rendRect.MaxY);
3287 /* Draw the Sort indicator .. */
3288 if (index == data->icld_LVMAttribs->lmva_SortColumn)
3290 LONG x = rendRect.MaxX - 4 - 6;
3291 LONG y = (rendRect.MinY + rendRect.MaxY + 1) / 2 - 3;
3293 if (x > rendRect.MinX)
3295 SetAPen(data->icld_BufferRastPort, _pens(obj)[sel ? MPEN_SHADOW : MPEN_HALFSHADOW]);
3296 if (data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
3298 RectFill(data->icld_BufferRastPort, x, y, x + 5, y + 1);
3299 RectFill(data->icld_BufferRastPort, x + 1, y + 2, x + 4, y + 3);
3300 RectFill(data->icld_BufferRastPort, x + 2, y + 4, x + 3, y + 5);
3302 else
3304 RectFill(data->icld_BufferRastPort, x, y + 4, x + 5, y + 5);
3305 RectFill(data->icld_BufferRastPort, x + 1, y + 2, x + 4, y + 3);
3306 RectFill(data->icld_BufferRastPort, x + 2, y, x + 3, y + 1);
3311 rendRect.MinX += HEADERENTRY_SPACING_LEFT;
3312 rendRect.MinY += HEADERLINE_SPACING_TOP;
3313 rendRect.MaxX -= HEADERENTRY_SPACING_RIGHT;
3314 rendRect.MaxY -= HEADERLINE_SPACING_BOTTOM;
3316 if (text && text[0])
3319 fit = TextFit(data->icld_BufferRastPort, text, strlen(text), &te, NULL, 1,
3320 rendRect.MaxX - rendRect.MinX + 1,
3321 rendRect.MaxY - rendRect.MinY + 1);
3323 if (!fit) return;
3325 SetABPenDrMd(data->icld_BufferRastPort, penText, 0, JAM1);
3326 Move(data->icld_BufferRastPort, rendRect.MinX, rendRect.MinY + data->icld_BufferRastPort->TxBaseline);
3327 Text(data->icld_BufferRastPort, text, fit);
3332 static void RenderListViewModeHeader(Object *obj, struct IconList_DATA *data)
3334 struct Rectangle linerect;
3335 LONG x, i;
3336 LONG firstvis, lastvis;
3338 #if defined(DEBUG_ILC_FUNCS)
3339 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
3340 #endif
3342 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
3344 linerect.MinX = _mleft(obj) - data->icld_ViewX;
3345 linerect.MaxX = _mright(obj);
3346 linerect.MinY = _mtop(obj);
3347 linerect.MaxY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight - 1;
3349 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
3351 x = linerect.MinX + HEADERLINE_SPACING_LEFT;
3353 firstvis = FirstVisibleColumnNumber(data);
3354 lastvis = LastVisibleColumnNumber(data);
3356 for(i = 0; i < NUM_COLUMNS; i++)
3358 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
3360 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
3362 struct Rectangle field_rect;
3364 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
3365 field_rect.MinY = linerect.MinY;
3366 field_rect.MaxX = x + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1 + ((i == lastvis) ? HEADERLINE_SPACING_RIGHT : 0);
3367 field_rect.MaxY = linerect.MaxY;
3369 /* data->update_rect1 and data->update_rect2 may
3370 point to rectangles to indicate that only icons
3371 in any of this rectangles need to be drawn */
3372 if (data->update_rect1)
3374 RectAndRect(&field_rect, data->update_rect1);
3377 if (data->update_rect2)
3379 RectAndRect(&field_rect, data->update_rect2);
3382 RenderListViewModeHeaderField(obj, data, &field_rect, index, FALSE);
3383 x += data->icld_LVMAttribs->lmva_ColumnWidth[index];
3386 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_HEADERDRAWTOEND) == LVMAF_HEADERDRAWTOEND)
3388 x += HEADERLINE_SPACING_RIGHT;
3390 if (x < linerect.MaxX)
3392 linerect.MinX = x;
3394 // if (MustRenderRect(data, &linerect))
3395 // {
3396 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_HALFSHINE], 0, JAM1);
3397 RectFill(data->icld_BufferRastPort, linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
3398 // }
3404 ///MUIM_Draw()
3405 /**************************************************************************
3406 MUIM_Draw - draw the IconList
3407 **************************************************************************/
3408 IPTR DrawCount;
3409 IPTR IconList__MUIM_Draw(struct IClass *CLASS, Object *obj, struct MUIP_Draw *message)
3411 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3412 struct IconEntry *entry = NULL;
3414 APTR clip = NULL;
3416 ULONG update_oldwidth = 0,
3417 update_oldheight = 0;
3419 LONG clear_xoffset = 0,
3420 clear_yoffset = 0;
3422 __unused IPTR draw_id = DrawCount++;
3424 #if defined(DEBUG_ILC_FUNCS)
3425 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
3426 #endif
3427 #if defined(DEBUG_ILC_ICONRENDERING)
3428 D(bug("[IconList] %s: id %d\n", __PRETTY_FUNCTION__, draw_id));
3429 #endif
3431 DoSuperMethodA(CLASS, obj, (Msg)message);
3433 if (!(data->icld__Option_IconListFixedBackground))
3435 clear_xoffset = data->icld_ViewX;
3436 clear_yoffset = data->icld_ViewY;
3439 // If window size changes, only update needed areas
3440 if (data->update_oldwidth == 0) data->update_oldwidth = data->icld_ViewWidth;
3441 if (data->update_oldheight == 0) data->update_oldheight = data->icld_ViewHeight;
3442 if ((data->update_oldwidth != data->icld_ViewWidth) || (data->update_oldheight != data->icld_ViewHeight))
3444 if (data->icld_UpdateMode != UPDATE_SCROLL)
3446 data->icld_UpdateMode = UPDATE_RESIZE;
3447 update_oldwidth = data->update_oldwidth;
3448 update_oldheight = data->update_oldheight;
3449 data->update_oldwidth = data->icld_ViewWidth;
3450 data->update_oldheight = data->icld_ViewHeight;
3454 if ((message->flags & MADF_DRAWUPDATE) || (data->icld_UpdateMode == UPDATE_RESIZE))
3456 #if defined(DEBUG_ILC_ICONRENDERING)
3458 if (message->flags & MADF_DRAWUPDATE)
3460 bug("[IconList] %s#%d: MADF_DRAWUPDATE\n", __PRETTY_FUNCTION__, draw_id);
3462 else
3464 bug("[IconList] %s#%d: UPDATE_RESIZE\n", __PRETTY_FUNCTION__, draw_id);
3467 #endif
3468 if ((data->icld_UpdateMode == UPDATE_HEADERENTRY) && ((IPTR)data->update_entry < NUM_COLUMNS)) /* draw the header entry */
3470 struct Rectangle field_rect;
3471 LONG index, i, firstvis, lastvis;
3473 firstvis = FirstVisibleColumnNumber(data);
3474 lastvis = LastVisibleColumnNumber(data);
3476 field_rect.MinX = _mleft(obj) - data->icld_ViewX;
3478 field_rect.MinY = _mtop(obj);
3479 field_rect.MaxY = field_rect.MinY + data->icld_LVMAttribs->lmva_HeaderHeight - 1;
3481 for(i = 0; i < NUM_COLUMNS; i++)
3483 index = data->icld_LVMAttribs->lmva_ColumnPos[i];
3484 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
3486 field_rect.MaxX = field_rect.MinX + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1;
3487 if (index == lastvis)
3488 field_rect.MaxX += HEADERLINE_SPACING_RIGHT;
3490 if ((IPTR)data->update_entry != index)
3492 field_rect.MinX += data->icld_LVMAttribs->lmva_ColumnWidth[index];
3493 if (index == firstvis)
3494 field_rect.MinX += HEADERLINE_SPACING_LEFT;
3496 else
3497 break;
3500 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mright(obj) - _mleft(obj) + 1, data->icld_LVMAttribs->lmva_HeaderHeight);
3502 if (data->icld_LVMAttribs->lmva_LastSelectedColumn == (IPTR)data->update_entry)
3503 RenderListViewModeHeaderField(obj, data, &field_rect, (IPTR)data->update_entry, TRUE);
3504 else
3505 RenderListViewModeHeaderField(obj, data, &field_rect, (IPTR)data->update_entry, FALSE);
3507 data->icld_UpdateMode = 0;
3508 data->update_entry = NULL;
3510 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3512 #if defined(DEBUG_ILC_ICONRENDERING)
3513 D(bug("[IconList] %s#%d: UPDATE_HEADERENTRY Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3514 #endif
3515 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3516 field_rect.MinX - _mleft(obj), field_rect.MinY - _mtop(obj),
3517 data->icld_DisplayRastPort,
3518 field_rect.MinX, field_rect.MinY,
3519 field_rect.MaxX - field_rect.MinX + 1, field_rect.MaxY - field_rect.MinY + 1,
3520 0xC0);
3522 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3524 goto draw_done;
3526 else if ((data->icld_UpdateMode == UPDATE_SINGLEENTRY) && (data->update_entry != NULL)) /* draw only a single entry at update_entry */
3528 struct Rectangle rect;
3530 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3532 LONG count = 0, index = -1;
3534 #if defined(DEBUG_ILC_ICONRENDERING)
3535 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY + ICONLIST_DISP_MODELIST\n", __PRETTY_FUNCTION__, draw_id));
3536 #endif
3537 rect.MinX = _mleft(obj);
3538 rect.MaxX = _mleft(obj) + _mwidth(obj) - 1;
3540 ForeachNode(&data->icld_IconList, entry)
3542 if (entry == data->update_entry)
3544 index = count;
3545 break;
3547 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
3549 count++;
3553 if (index != -1)
3555 rect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight - data->icld_ViewY + (index * data->icld_LVMAttribs->lmva_RowHeight);
3556 rect.MaxY = rect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
3558 if ((rect.MaxY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight))
3559 || (rect.MinY > (_mtop(obj) + _mheight(obj) - 1)))
3560 goto draw_done;
3562 if (rect.MinY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight)) rect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight;
3563 if (rect.MaxY > (_mtop(obj) + _mheight(obj) - 1)) rect.MaxY = _mtop(obj) + _mheight(obj) - 1;
3565 clip = MUI_AddClipping(muiRenderInfo(obj), rect.MinX, rect.MinY, rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1);
3567 DoMethod(obj, MUIM_DrawBackground,
3568 rect.MinX, rect.MinY,
3569 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3570 clear_xoffset, clear_yoffset,
3573 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3574 DoMethod(obj, MUIM_IconList_DrawEntry, data->update_entry, index);
3575 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3576 data->icld_UpdateMode = 0;
3577 data->update_entry = NULL;
3580 else
3582 #if defined(DEBUG_ILC_ICONRENDERING)
3583 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY (entry @ 0x%p)\n", __PRETTY_FUNCTION__, draw_id, data->update_entry));
3584 #endif
3585 IconList_GetIconAreaRectangle(obj, data, data->update_entry, &rect);
3587 rect.MinX += _mleft(obj) + (data->update_entry->ie_IconX - data->icld_ViewX);
3588 rect.MaxX += _mleft(obj) + (data->update_entry->ie_IconX - data->icld_ViewX);
3589 rect.MinY += _mtop(obj) + (data->update_entry->ie_IconY - data->icld_ViewY);
3590 rect.MaxY += _mtop(obj) + (data->update_entry->ie_IconY - data->icld_ViewY);
3592 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
3594 if (data->update_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
3596 rect.MinX += ((data->icld_IconAreaLargestWidth - data->update_entry->ie_AreaWidth)/2);
3597 rect.MaxX += ((data->icld_IconAreaLargestWidth - data->update_entry->ie_AreaWidth)/2);
3600 if (data->update_entry->ie_AreaHeight < data->icld_IconAreaLargestHeight)
3602 rect.MinY += ((data->icld_IconAreaLargestHeight - data->update_entry->ie_AreaHeight)/2);
3603 rect.MaxY += ((data->icld_IconAreaLargestHeight - data->update_entry->ie_AreaHeight)/2);
3607 if (rect.MinX < _mleft(obj)) rect.MinX = _mleft(obj);
3608 if (rect.MaxX > _mright(obj)) rect.MaxX =_mright(obj);
3609 if (rect.MinY < _mtop(obj)) rect.MinY = _mtop(obj);
3610 if (rect.MaxY > _mbottom(obj)) rect.MaxY = _mbottom(obj);
3612 clip = MUI_AddClipping(muiRenderInfo(obj), rect.MinX, rect.MinY, rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1);
3614 #if defined(DEBUG_ILC_ICONRENDERING)
3615 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY: Calling MUIM_DrawBackground (A)\n", __PRETTY_FUNCTION__, draw_id));
3616 #endif
3617 DoMethod(obj, MUIM_DrawBackground,
3618 rect.MinX, rect.MinY,
3619 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3620 clear_xoffset, clear_yoffset,
3623 /* We could have deleted also other icons so they must be redrawn */
3624 #if defined(__AROS__)
3625 ForeachNode(&data->icld_IconList, entry)
3626 #else
3627 Foreach_Node(&data->icld_IconList, entry);
3628 #endif
3630 if ((entry != data->update_entry) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
3632 struct Rectangle rect2;
3633 IconList_GetIconAreaRectangle(obj, data, entry, &rect2);
3635 rect2.MinX += _mleft(obj) - data->icld_ViewX + entry->ie_IconX;
3636 rect2.MaxX += _mleft(obj) - data->icld_ViewX + entry->ie_IconX;
3637 rect2.MinY += _mtop(obj) - data->icld_ViewY + entry->ie_IconY;
3638 rect2.MaxY += _mtop(obj) - data->icld_ViewY + entry->ie_IconY;
3640 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
3642 if (entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
3644 rect2.MinX += ((data->icld_IconAreaLargestWidth - entry->ie_AreaWidth)/2);
3645 rect2.MaxX += ((data->icld_IconAreaLargestWidth - entry->ie_AreaWidth)/2);
3648 if (entry->ie_AreaHeight < data->icld_IconAreaLargestHeight)
3650 rect2.MinY += ((data->icld_IconAreaLargestHeight - entry->ie_AreaHeight)/2);
3651 rect2.MaxY += ((data->icld_IconAreaLargestHeight - entry->ie_AreaHeight)/2);
3655 if (RectAndRect(&rect, &rect2))
3657 // Update entry here
3658 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3659 DoMethod(obj, MUIM_IconList_DrawEntry, entry, ICONENTRY_DRAWMODE_PLAIN);
3660 DoMethod(obj, MUIM_IconList_DrawEntryLabel, entry, ICONENTRY_DRAWMODE_PLAIN);
3661 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3666 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3667 DoMethod(obj, MUIM_IconList_DrawEntry, data->update_entry, ICONENTRY_DRAWMODE_PLAIN);
3668 DoMethod(obj, MUIM_IconList_DrawEntryLabel, data->update_entry, ICONENTRY_DRAWMODE_PLAIN);
3669 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3670 data->icld_UpdateMode = 0;
3671 data->update_entry = NULL;
3673 if (data->update_entry == NULL)
3675 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3677 #if defined(DEBUG_ILC_ICONRENDERING)
3678 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3679 #endif
3680 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3681 rect.MinX - _mleft(obj), rect.MinY - _mtop(obj),
3682 data->icld_DisplayRastPort,
3683 rect.MinX, rect.MinY,
3684 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3685 0xC0);
3687 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3689 goto draw_done;
3691 else if (data->icld_UpdateMode == UPDATE_SCROLL)
3693 struct Region *region = NULL;
3694 struct Rectangle xrect,
3695 yrect;
3696 BOOL scroll_caused_damage = FALSE;
3698 #if defined(DEBUG_ILC_ICONRENDERING)
3699 D(bug("[IconList] %s#%d: UPDATE_SCROLL.\n", __PRETTY_FUNCTION__, draw_id));
3700 #endif
3702 if (!data->icld__Option_IconListFixedBackground)
3704 scroll_caused_damage = (_rp(obj)->Layer->Flags & LAYERREFRESH) ? FALSE : TRUE;
3706 data->icld_UpdateMode = 0;
3708 if ((abs(data->update_scrolldx) >= _mwidth(obj)) ||
3709 (abs(data->update_scrolldy) >= _mheight(obj)))
3711 #if defined(DEBUG_ILC_ICONRENDERING)
3712 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Moved outside current view -> Causing Redraw .. MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3713 #endif
3714 MUI_Redraw(obj, MADF_DRAWOBJECT);
3715 goto draw_done;
3718 if (!(region = NewRegion()))
3720 #if defined(DEBUG_ILC_ICONRENDERING)
3721 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Couldnt Alloc Region -> Causing Redraw ...MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3722 #endif
3723 MUI_Redraw(obj, MADF_DRAWOBJECT);
3724 goto draw_done;
3727 if (data->update_scrolldx > 0)
3729 xrect.MinX = _mright(obj) - data->update_scrolldx;
3730 xrect.MinY = _mtop(obj);
3731 xrect.MaxX = _mright(obj);
3732 xrect.MaxY = _mbottom(obj);
3734 OrRectRegion(region, &xrect);
3736 data->update_rect1 = &xrect;
3738 else if (data->update_scrolldx < 0)
3740 xrect.MinX = _mleft(obj);
3741 xrect.MinY = _mtop(obj);
3742 xrect.MaxX = _mleft(obj) - data->update_scrolldx;
3743 xrect.MaxY = _mbottom(obj);
3745 OrRectRegion(region, &xrect);
3747 data->update_rect1 = &xrect;
3750 if (data->update_scrolldy > 0)
3752 yrect.MinX = _mleft(obj);
3753 yrect.MinY = _mbottom(obj) - data->update_scrolldy;
3754 if (((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3755 && (yrect.MinY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight)))
3757 xrect.MinY = data->icld_LVMAttribs->lmva_HeaderHeight;
3759 yrect.MaxX = _mright(obj);
3760 yrect.MaxY = _mbottom(obj);
3762 OrRectRegion(region, &yrect);
3764 data->update_rect2 = &yrect;
3766 else if (data->update_scrolldy < 0)
3768 yrect.MinX = _mleft(obj);
3769 yrect.MinY = _mtop(obj);
3770 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3772 xrect.MinY += data->icld_LVMAttribs->lmva_HeaderHeight;
3774 yrect.MaxX = _mright(obj);
3775 yrect.MaxY = _mtop(obj) - data->update_scrolldy;
3777 OrRectRegion(region, &yrect);
3779 data->update_rect2 = &yrect;
3782 #if defined(DEBUG_ILC_ICONRENDERING)
3783 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Scrolling Raster..\n", __PRETTY_FUNCTION__, draw_id));
3784 #endif
3785 if (data->icld_DisplayRastPort == data->icld_BufferRastPort)
3787 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3789 ScrollRasterBF(data->icld_BufferRastPort,
3790 data->update_scrolldx,
3791 data->update_scrolldy,
3792 _mleft(obj),
3793 _mtop(obj) + (data->update_scrolldx ? 0 : data->icld_LVMAttribs->lmva_HeaderHeight),
3794 _mright(obj),
3795 _mbottom(obj));
3797 else
3799 ScrollRasterBF(data->icld_BufferRastPort,
3800 data->update_scrolldx,
3801 data->update_scrolldy,
3802 _mleft(obj),
3803 _mtop(obj),
3804 _mright(obj),
3805 _mbottom(obj));
3808 else
3810 ScrollRasterBF(data->icld_BufferRastPort,
3811 data->update_scrolldx,
3812 data->update_scrolldy,
3815 _mwidth(obj) - 1,
3816 _mheight(obj) - 1);
3819 scroll_caused_damage = scroll_caused_damage && (_rp(obj)->Layer->Flags & LAYERREFRESH) ? TRUE : FALSE;
3821 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
3824 #if defined(DEBUG_ILC_ICONRENDERING)
3825 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3826 #endif
3827 MUI_Redraw(obj, MADF_DRAWOBJECT);
3829 data->update_rect1 = data->update_rect2 = NULL;
3831 if (!data->icld__Option_IconListFixedBackground)
3833 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
3835 if (scroll_caused_damage)
3837 if (MUI_BeginRefresh(muiRenderInfo(obj), 0))
3839 /* Theoretically it might happen that more damage is caused
3840 after ScrollRaster. By something else, like window movement
3841 in front of our window. Therefore refresh root object of
3842 window, not just this object */
3844 Object *o = NULL;
3846 GET(_win(obj),MUIA_Window_RootObject, &o);
3847 MUI_Redraw(o, MADF_DRAWOBJECT);
3848 #if defined(DEBUG_ILC_ICONRENDERING)
3849 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3850 #endif
3851 MUI_EndRefresh(muiRenderInfo(obj), 0);
3855 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3857 #if defined(DEBUG_ILC_ICONRENDERING)
3858 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3859 #endif
3860 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3861 0, 0,
3862 data->icld_DisplayRastPort,
3863 _mleft(obj), _mtop(obj),
3864 _mwidth(obj), _mheight(obj),
3865 0xC0);
3867 goto draw_done;
3869 else if (data->icld_UpdateMode == UPDATE_RESIZE)
3871 struct Region *region = NULL;
3872 struct Rectangle wrect,
3873 hrect;
3874 ULONG diffw = 0,
3875 diffh = 0;
3877 #if defined(DEBUG_ILC_ICONRENDERING)
3878 D(bug("[IconList] %s#%d: UPDATE_RESIZE.\n", __PRETTY_FUNCTION__, draw_id));
3879 #endif
3881 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
3883 //Free up the buffers Layer, rastport and bitmap so we can replace them ..
3884 if ((GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_WIDTH) != data->icld_ViewWidth)
3885 || (GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_HEIGHT) != data->icld_ViewHeight))
3887 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
3888 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
3889 D(bug("[IconList] %s: Destroying old BackLayer\n", __PRETTY_FUNCTION__));
3890 #endif
3891 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3892 DeleteLayer(0, oldLayer);
3895 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
3897 struct BitMap *bitmap_New;
3898 ULONG tmp_RastDepth;
3899 struct Layer_Info *li = NULL;
3901 tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
3902 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
3903 data->icld_ViewHeight,
3904 tmp_RastDepth,
3905 BMF_CLEAR,
3906 data->icld_DisplayRastPort->BitMap)) != NULL)
3908 if ((data->icld_BufferRastPort = CreateRastPort()) != NULL)
3910 data->icld_BufferRastPort->BitMap = bitmap_New;
3911 if ((li = NewLayerInfo()))
3913 if ((data->icld_BufferRastPort->Layer = CreateUpfrontLayer(li, data->icld_BufferRastPort->BitMap, 0, 0, data->icld_ViewWidth - 1, data->icld_ViewHeight - 1, 0, NULL)))
3916 * Mark it as a buffered rastport.
3919 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
3920 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
3921 #endif
3922 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
3923 data->icld_DrawOffsetX = 0;
3924 data->icld_DrawOffsetY = 0;
3926 else
3927 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3929 else
3930 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3932 else
3933 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3936 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
3938 if (bitmap_New) FreeBitMap(bitmap_New);
3939 if (li) DisposeLayerInfo(li);
3940 data->icld_DrawOffsetX = _mleft(obj);
3941 data->icld_DrawOffsetY = _mtop(obj);
3946 data->icld_UpdateMode = 0;
3948 if (!data->icld__Option_IconListScaledBackground)
3950 if (!(region = NewRegion()))
3952 #if defined(DEBUG_ILC_ICONRENDERING)
3953 D(bug("[IconList] %s#%d: UPDATE_RESIZE: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3954 #endif
3955 MUI_Redraw(obj, MADF_DRAWOBJECT);
3956 goto draw_done;
3959 if ( data->icld_ViewWidth > update_oldwidth )
3960 diffw = data->icld_ViewWidth - update_oldwidth;
3961 if ( data->icld_ViewHeight > update_oldheight )
3962 diffh = data->icld_ViewHeight - update_oldheight;
3964 if (diffw)
3966 wrect.MinX = _mright(obj) - diffw;
3967 wrect.MinY = _mtop(obj);
3968 wrect.MaxX = _mright(obj);
3969 wrect.MaxY = _mbottom(obj);
3970 OrRectRegion(region, &wrect);
3971 data->update_rect1 = &wrect;
3974 if (diffh)
3976 hrect.MinX = _mleft(obj);
3977 hrect.MinY = _mbottom(obj) - diffh;
3978 hrect.MaxX = _mright(obj);
3979 hrect.MaxX = _mright(obj);
3980 hrect.MaxY = _mbottom(obj);
3981 OrRectRegion(region, &hrect);
3982 data->update_rect2 = &hrect;
3984 if (diffh||diffw)
3986 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
3988 else
3990 /* View became smaller both in horizontal and vertical direction.
3991 Nothing to do */
3993 DisposeRegion(region);
3994 goto draw_done;
3998 #if defined(DEBUG_ILC_ICONRENDERING)
3999 D(bug("[IconList] %s#%d: UPDATE_RESIZE: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
4000 #endif
4001 MUI_Redraw(obj, MADF_DRAWOBJECT);
4003 if (!data->icld__Option_IconListScaledBackground)
4005 if (diffh||diffw)
4007 data->update_rect1 = data->update_rect2 = NULL;
4008 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
4009 } else DisposeRegion(region);
4012 goto draw_done;
4016 if (message->flags & MADF_DRAWOBJECT)
4018 struct Rectangle viewrect;
4019 int current = 0, first = 0, visible = 0;
4021 #if defined(DEBUG_ILC_ICONRENDERING)
4022 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
4023 #endif
4025 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
4027 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), data->icld_LVMAttribs->lmva_HeaderHeight);
4028 RenderListViewModeHeader(obj, data);
4030 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
4032 #if defined(DEBUG_ILC_ICONRENDERING)
4033 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT Blitting Header to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
4034 #endif
4035 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
4036 0, 0,
4037 data->icld_DisplayRastPort,
4038 _mleft(obj), _mtop(obj), _mwidth(obj), data->icld_LVMAttribs->lmva_HeaderHeight,
4039 0xC0);
4042 MUI_RemoveClipping(muiRenderInfo(obj), clip);
4044 viewrect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight;
4046 first = FirstVisibleLine(data);
4047 visible = NumVisibleLines(data);
4049 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight, _mwidth(obj), _mheight(obj) - data->icld_LVMAttribs->lmva_HeaderHeight);
4051 else
4053 viewrect.MinY = _mtop(obj);
4054 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj));
4057 viewrect.MaxY = _mtop(obj) + _mheight(obj) - 1;
4058 viewrect.MinX = _mleft(obj);
4059 viewrect.MaxX = _mleft(obj) + _mwidth(obj) - 1;
4061 #if defined(DEBUG_ILC_ICONRENDERING)
4062 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT: Calling MUIM_DrawBackground (B)\n", __PRETTY_FUNCTION__, draw_id));
4063 #endif
4064 DoMethod(
4065 obj, MUIM_DrawBackground, viewrect.MinX, viewrect.MinY, (viewrect.MaxX - viewrect.MinX) + 1, (viewrect.MaxY - viewrect.MinY) + 1,
4066 clear_xoffset, clear_yoffset, 0
4068 #if defined(__AROS__)
4069 ForeachNode(&data->icld_IconList, entry)
4070 #else
4071 Foreach_Node(&data->icld_IconList, entry);
4072 #endif
4074 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
4076 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4078 if ((current >= first) && (current <= (first + visible)))
4080 DoMethod(obj, MUIM_IconList_DrawEntry, entry, current);
4082 current++;
4085 else
4087 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
4088 (entry->ie_DiskObj) &&
4089 (entry->ie_IconX != NO_ICON_POSITION) &&
4090 (entry->ie_IconY != NO_ICON_POSITION))
4092 struct Rectangle iconrect;
4093 IconList_GetIconAreaRectangle(obj, data, entry, &iconrect);
4095 iconrect.MinX += viewrect.MinX - data->icld_ViewX + entry->ie_IconX;
4096 iconrect.MaxX += viewrect.MinX - data->icld_ViewX + entry->ie_IconX;
4097 iconrect.MinY += viewrect.MinY - data->icld_ViewY + entry->ie_IconY;
4098 iconrect.MaxY += viewrect.MinY - data->icld_ViewY + entry->ie_IconY;
4100 if (RectAndRect(&viewrect, &iconrect))
4102 DoMethod(obj, MUIM_IconList_DrawEntry, entry, ICONENTRY_DRAWMODE_PLAIN);
4103 DoMethod(obj, MUIM_IconList_DrawEntryLabel, entry, ICONENTRY_DRAWMODE_PLAIN);
4109 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
4111 #if defined(DEBUG_ILC_ICONRENDERING)
4112 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT: Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
4113 #endif
4114 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
4115 0, 0,
4116 data->icld_DisplayRastPort,
4117 _mleft(obj), _mtop(obj),
4118 _mwidth(obj), _mheight(obj),
4119 0xC0);
4122 MUI_RemoveClipping(muiRenderInfo(obj), clip);
4124 data->icld_UpdateMode = 0;
4126 draw_done:;
4128 #if defined(DEBUG_ILC_ICONRENDERING)
4129 D(bug("[IconList] %s: Draw finished for id %d\n", __PRETTY_FUNCTION__, draw_id));
4130 #endif
4131 return 0;
4135 ///IconList__MUIM_IconList_Update()
4136 /**************************************************************************
4137 MUIM_IconList_Refresh
4138 Implemented by subclasses
4139 **************************************************************************/
4140 IPTR IconList__MUIM_IconList_Update(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Update *message)
4142 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4144 #if defined(DEBUG_ILC_FUNCS)
4145 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4146 #endif
4148 data->icld_FocusIcon = NULL;
4149 SET(obj, MUIA_IconList_Changed, TRUE);
4151 return 1;
4155 ///MUIM_IconList_Clear()
4156 /**************************************************************************
4157 MUIM_IconList_Clear
4158 **************************************************************************/
4159 IPTR IconList__MUIM_IconList_Clear(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Clear *message)
4161 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4162 struct IconEntry *node = NULL;
4164 #if defined(DEBUG_ILC_FUNCS)
4165 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4166 #endif
4168 while ((node = (struct IconEntry*)RemTail((struct List*)&data->icld_IconList)))
4170 DoMethod(obj, MUIM_IconList_DestroyEntry, node);
4173 data->icld_SelectionLastClicked = NULL;
4174 data->icld_FocusIcon = NULL;
4176 data->icld_ViewX = data->icld_ViewY = data->icld_AreaWidth = data->icld_AreaHeight = 0;
4177 data->icld_IconAreaLargestWidth = 0;
4178 data->icld_IconAreaLargestHeight = 0;
4179 data->icld_IconLargestHeight = 0;
4180 data->icld_LabelLargestHeight = 0;
4182 #if defined(DEBUG_ILC_ICONRENDERING)
4183 D(bug("[IconList]: %s: call SetSuperAttrs()\n", __PRETTY_FUNCTION__));
4184 #endif
4185 SetSuperAttrs(CLASS, obj, MUIA_Virtgroup_Left, data->icld_ViewX,
4186 MUIA_Virtgroup_Top, data->icld_ViewY,
4187 TAG_DONE);
4189 #if defined(DEBUG_ILC_ICONRENDERING)
4190 D(bug("[IconList]: %s: call SetAttrs()\n", __PRETTY_FUNCTION__));
4191 #endif
4192 SetAttrs(obj, MUIA_Virtgroup_Left, data->icld_ViewX,
4193 MUIA_Virtgroup_Top, data->icld_ViewY,
4194 TAG_DONE);
4196 #if defined(DEBUG_ILC_ICONRENDERING)
4197 D(bug("[IconList]: %s: Set MUIA_IconList_Width and MUIA_IconList_Height\n", __PRETTY_FUNCTION__));
4198 #endif
4199 SetAttrs(obj, MUIA_IconList_Width, data->icld_AreaWidth,
4200 MUIA_IconList_Height, data->icld_AreaHeight,
4201 TAG_DONE);
4203 D(bug("[IconList]: %s: call MUI_Redraw()\n", __PRETTY_FUNCTION__));
4204 MUI_Redraw(obj,MADF_DRAWOBJECT);
4205 return 1;
4209 ///IconList__MUIM_IconList_DestroyEntry()
4210 IPTR IconList__MUIM_IconList_DestroyEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DestroyEntry *message)
4212 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4214 #if defined(DEBUG_ILC_FUNCS)
4215 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4216 #endif
4218 if (message->entry)
4220 if (message->entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
4222 if (data->icld_SelectionLastClicked == message->entry)
4224 struct IconList_Entry *nextentry = &message->entry->ie_IconListEntry;
4226 /* get selected entries from SOURCE iconlist */
4227 DoMethod(obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&nextentry);
4228 if ((nextentry) && ((IPTR)nextentry != MUIV_IconList_NextIcon_End))
4229 data->icld_SelectionLastClicked = (struct IconEntry *)((IPTR)nextentry - ((IPTR)&message->entry->ie_IconListEntry - (IPTR)message->entry));
4230 else
4231 data->icld_SelectionLastClicked = NULL;
4233 if (data->icld_FocusIcon == message->entry)
4234 data->icld_FocusIcon = data->icld_SelectionLastClicked;
4236 Remove(&message->entry->ie_SelectionNode);
4239 if (message->entry->ie_TxtBuf_DisplayedLabel)
4240 FreeVecPooled(data->icld_Pool, message->entry->ie_TxtBuf_DisplayedLabel);
4242 if (message->entry->ie_TxtBuf_PROT)
4243 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_PROT, 8);
4245 if (message->entry->ie_TxtBuf_SIZE)
4246 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_SIZE, 30);
4248 if (message->entry->ie_TxtBuf_TIME)
4249 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_TIME, LEN_DATSTRING);
4251 if (message->entry->ie_TxtBuf_DATE)
4252 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_DATE, LEN_DATSTRING);
4254 if (message->entry->ie_DiskObj)
4255 FreeDiskObject(message->entry->ie_DiskObj);
4257 if (message->entry->ie_FileInfoBlock)
4258 FreeMem(message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4260 if (message->entry->ie_IconListEntry.label)
4261 FreePooled(data->icld_Pool, message->entry->ie_IconListEntry.label, strlen(message->entry->ie_IconListEntry.label)+1);
4263 if (message->entry->ie_IconNode.ln_Name)
4264 FreePooled(data->icld_Pool, message->entry->ie_IconNode.ln_Name, strlen(message->entry->ie_IconNode.ln_Name)+1);
4266 FreePooled(data->icld_Pool, message->entry, sizeof(struct IconEntry));
4268 return (IPTR)TRUE;
4272 ///IconList__MUIM_IconList_PropagateEntryPos()
4273 IPTR IconList__MUIM_IconList_PropagateEntryPos(struct IClass *CLASS, Object *obj,
4274 struct MUIP_IconList_PropagateEntryPos *message)
4276 message->entry->ie_ProvidedIconX = message->entry->ie_IconX;
4277 message->entry->ie_ProvidedIconY = message->entry->ie_IconY;
4279 return (IPTR)TRUE;
4283 ///IconList__MUIM_IconList_CreateEntry()
4284 /**************************************************************************
4285 MUIM_IconList_CreateEntry.
4286 Returns 0 on failure; otherwise it returns the icon's entry.
4287 **************************************************************************/
4288 IPTR IconList__MUIM_IconList_CreateEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_CreateEntry *message)
4290 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4291 struct IconEntry *entry = NULL;
4292 struct DateTime dt;
4293 struct DateStamp now;
4294 UBYTE *sp = NULL;
4296 struct DiskObject *dob = NULL;
4297 struct Rectangle rect;
4299 IPTR geticon_error = 0;
4301 #if defined(DEBUG_ILC_FUNCS)
4302 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4303 #endif
4305 if (message->filename == NULL) {
4306 D(bug("[IconList] %s: IconList - filename was NULL\n", __PRETTY_FUNCTION__));
4307 return (IPTR)NULL;
4310 /*disk object (icon)*/
4311 if (message->entry_dob == NULL)
4313 IPTR iconlistScreen = (IPTR)_screen(obj);
4314 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
4316 dob = GetIconTags
4318 message->filename,
4319 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
4320 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
4321 ICONGETA_FailIfUnavailable, FALSE,
4322 ICONGETA_GenerateImageMasks, TRUE,
4323 ICONA_ErrorCode, &geticon_error,
4324 TAG_DONE
4327 if (dob == NULL)
4329 D(bug("[IconList] %s: Fatal: Couldnt get DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
4331 return (IPTR)NULL;
4334 else
4336 dob = message->entry_dob;
4339 D(bug("[IconList] %s: DiskObject @ 0x%p\n", __PRETTY_FUNCTION__, dob));
4341 if ((entry = AllocPooled(data->icld_Pool, sizeof(struct IconEntry))) == NULL)
4343 D(bug("[IconList] %s: Failed to Allocate Entry Storage!\n", __PRETTY_FUNCTION__));
4344 FreeDiskObject(dob);
4345 return (IPTR)NULL;
4347 memset(entry, 0, sizeof(struct IconEntry));
4348 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4349 entry->ie_IconListEntry.ile_IconEntry = entry;
4351 /* Allocate Text Buffers */
4353 if ((entry->ie_TxtBuf_DATE = AllocPooled(data->icld_Pool, LEN_DATSTRING)) == NULL)
4355 D(bug("[IconList] %s: Failed to Allocate Entry DATE Storage!\n", __PRETTY_FUNCTION__));
4356 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4357 return (IPTR)NULL;
4359 memset(entry->ie_TxtBuf_DATE, 0, LEN_DATSTRING);
4361 if ((entry->ie_TxtBuf_TIME = AllocPooled(data->icld_Pool, LEN_DATSTRING)) == NULL)
4363 D(bug("[IconList] %s: Failed to Allocate Entry TIME string Storage!\n", __PRETTY_FUNCTION__));
4364 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4365 return (IPTR)NULL;
4367 memset(entry->ie_TxtBuf_TIME, 0, LEN_DATSTRING);
4369 if ((entry->ie_TxtBuf_SIZE = AllocPooled(data->icld_Pool, 30)) == NULL)
4371 D(bug("[IconList] %s: Failed to Allocate Entry SIZE string Storage!\n", __PRETTY_FUNCTION__));
4372 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4373 return (IPTR)NULL;
4375 memset(entry->ie_TxtBuf_SIZE, 0, 30);
4377 if ((entry->ie_TxtBuf_PROT = AllocPooled(data->icld_Pool, 8)) == NULL)
4379 D(bug("[IconList] %s: Failed to Allocate Entry PROT Flag string Storage!\n", __PRETTY_FUNCTION__));
4380 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4381 return (IPTR)NULL;
4383 memset(entry->ie_TxtBuf_PROT, 0, 8);
4385 /*alloc filename*/
4386 if ((entry->ie_IconNode.ln_Name = AllocPooled(data->icld_Pool, strlen(message->filename) + 1)) == NULL)
4388 D(bug("[IconList] %s: Failed to Allocate Entry filename string Storage!\n", __PRETTY_FUNCTION__));
4389 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4390 return (IPTR)NULL;
4393 /*alloc entry label*/
4394 if ((entry->ie_IconListEntry.label = AllocPooled(data->icld_Pool, strlen(message->label) + 1)) == NULL)
4396 D(bug("[IconList] %s: Failed to Allocate Entry label string Storage!\n", __PRETTY_FUNCTION__));
4397 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4398 return (IPTR)NULL;
4401 /*file info block*/
4402 if(message->fib != NULL)
4404 if ((entry->ie_FileInfoBlock = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)) != NULL)
4406 CopyMem(message->fib, entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4408 if (entry->ie_FileInfoBlock->fib_DirEntryType > 0)
4410 strcpy(entry->ie_TxtBuf_SIZE, "Drawer");
4412 else
4414 FmtSizeToString(entry->ie_TxtBuf_SIZE, entry->ie_FileInfoBlock->fib_Size);
4417 dt.dat_Stamp = entry->ie_FileInfoBlock->fib_Date;
4418 dt.dat_Format = FORMAT_DEF;
4419 dt.dat_Flags = 0;
4420 dt.dat_StrDay = NULL;
4421 dt.dat_StrDate = entry->ie_TxtBuf_DATE;
4422 dt.dat_StrTime = entry->ie_TxtBuf_TIME;
4424 DateToStr(&dt);
4425 DateStamp(&now);
4427 /*if modified today show time, otherwise just show date*/
4428 if (now.ds_Days == entry->ie_FileInfoBlock->fib_Date.ds_Days)
4429 entry->ie_Flags |= ICONENTRY_FLAG_TODAY;
4430 else
4431 entry->ie_Flags &= ~ICONENTRY_FLAG_TODAY;
4433 sp = entry->ie_TxtBuf_PROT;
4434 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_SCRIPT) ? 's' : '-';
4435 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_PURE) ? 'p' : '-';
4436 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
4437 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_READ) ? '-' : 'r';
4438 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_WRITE) ? '-' : 'w';
4439 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
4440 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_DELETE) ? '-' : 'd';
4441 *sp++ = '\0';
4443 entry->ie_IconListEntry.type = entry->ie_FileInfoBlock->fib_DirEntryType;
4446 else
4448 entry->ie_IconListEntry.type = ST_USERDIR;
4451 /* Override type if specified during CreateEntry */
4452 if (message->type != 0)
4454 entry->ie_IconListEntry.type = message->type;
4455 D(bug("[IconList] %s: Overide Entry Type. New Type = %x\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.type));
4457 else
4459 D(bug("[IconList] %s: Entry Type = %x\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.type));
4462 strcpy(entry->ie_IconNode.ln_Name, message->filename);
4463 strcpy(entry->ie_IconListEntry.label, message->label);
4465 entry->ie_IconListEntry.udata = message->udata;
4467 entry->ie_IconX = dob->do_CurrentX;
4468 entry->ie_IconY = dob->do_CurrentY;
4470 DoMethod(obj, MUIM_IconList_PropagateEntryPos, entry);
4472 if (IconList__LabelFunc_CreateLabel(obj, data, entry) != (IPTR)NULL)
4474 entry->ie_DiskObj = dob;
4476 /* Use a geticonrectangle routine that gets textwidth! */
4477 IconList_GetIconAreaRectangle(obj, data, entry, &rect);
4479 return (IPTR)entry;
4482 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4483 return (IPTR)NULL;
4487 ///IconList__MUIM_IconList_UpdateEntry()
4488 /**************************************************************************
4489 MUIM_IconList_UpdateEntry.
4490 Returns 0 on failure; otherwise it returns the icon's entry.
4491 **************************************************************************/
4492 IPTR IconList__MUIM_IconList_UpdateEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_UpdateEntry *message)
4494 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4495 // struct DateTime dt;
4496 // struct DateStamp now;
4497 // UBYTE *sp = NULL;
4499 // struct DiskObject *dob = NULL;
4500 struct Rectangle rect;
4502 // IPTR geticon_error = 0;
4504 #if defined(DEBUG_ILC_FUNCS)
4505 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4506 #endif
4508 /* Update disk object (icon)*/
4509 /* if (message->entry_dob == NULL)
4511 IPTR iconlistScreen = _screen(obj);
4512 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
4514 dob = GetIconTags
4516 message->filename,
4517 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
4518 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
4519 ICONGETA_FailIfUnavailable, FALSE,
4520 ICONGETA_GenerateImageMasks, TRUE,
4521 ICONA_ErrorCode, &geticon_error,
4522 TAG_DONE
4525 if (dob == NULL)
4527 D(bug("[IconList] %s: Fatal: Couldnt get DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
4529 return (IPTR)NULL;
4532 else
4534 dob = message->entry_dob;
4537 D(bug("[IconList] %s: DiskObject @ 0x%p\n", __PRETTY_FUNCTION__, dob));
4540 /* Update filename */
4541 if (strcmp(message->entry->ie_IconNode.ln_Name, message->filename) != 0)
4543 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4544 FreePooled(data->icld_Pool, message->entry->ie_IconNode.ln_Name, strlen(message->entry->ie_IconNode.ln_Name) + 1);
4545 if ((message->entry->ie_IconNode.ln_Name = AllocPooled(data->icld_Pool, strlen(message->filename) + 1)) == NULL)
4547 D(bug("[IconList] %s: Failed to Allocate Entry filename string Storage!\n", __PRETTY_FUNCTION__));
4548 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4549 return (IPTR)NULL;
4551 strcpy(message->entry->ie_IconNode.ln_Name, message->filename);
4554 /* Update entry label */
4555 if (strcmp(message->entry->ie_IconListEntry.label, message->label) != 0)
4557 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4558 FreePooled(data->icld_Pool, message->entry->ie_IconListEntry.label, strlen(message->entry->ie_IconListEntry.label) + 1);
4559 if ((message->entry->ie_IconListEntry.label = AllocPooled(data->icld_Pool, strlen(message->label) + 1)) == NULL)
4561 D(bug("[IconList] %s: Failed to Allocate Entry label string Storage!\n", __PRETTY_FUNCTION__));
4562 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4563 return (IPTR)NULL;
4565 strcpy(message->entry->ie_IconListEntry.label, message->label);
4566 if (IconList__LabelFunc_CreateLabel(obj, data, message->entry) == (IPTR)NULL)
4568 D(bug("[IconList] %s: Failed to create label\n", __PRETTY_FUNCTION__));
4569 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4570 return (IPTR)NULL;
4574 /* Update file info block */
4575 if(message->fib != NULL)
4577 if (!(message->entry->ie_FileInfoBlock))
4579 if ((message->entry->ie_FileInfoBlock = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)) != NULL)
4581 CopyMem(message->fib, message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4585 /* if (entry->ie_FileInfoBlock->fib_DirEntryType > 0)
4587 strcpy(entry->ie_TxtBuf_SIZE, "Drawer");
4589 else
4591 FmtSizeToString(entry->ie_TxtBuf_SIZE, entry->ie_FileInfoBlock->fib_Size);
4594 dt.dat_Stamp = entry->ie_FileInfoBlock->fib_Date;
4595 dt.dat_Format = FORMAT_DEF;
4596 dt.dat_Flags = 0;
4597 dt.dat_StrDay = NULL;
4598 dt.dat_StrDate = entry->ie_TxtBuf_DATE;
4599 dt.dat_StrTime = entry->ie_TxtBuf_TIME;
4601 DateToStr(&dt);
4602 DateStamp(&now);
4604 //if modified today show time, otherwise just show date
4605 if (now.ds_Days == entry->ie_FileInfoBlock->fib_Date.ds_Days)
4606 entry->ie_Flags |= ICONENTRY_FLAG_TODAY;
4607 else
4608 entry->ie_Flags &= ~ICONENTRY_FLAG_TODAY;
4610 sp = entry->ie_TxtBuf_PROT;
4611 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_SCRIPT) ? 's' : '-';
4612 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_PURE) ? 'p' : '-';
4613 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
4614 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_READ) ? '-' : 'r';
4615 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_WRITE) ? '-' : 'w';
4616 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
4617 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_DELETE) ? '-' : 'd';
4618 *sp++ = '\0';
4620 entry->ie_IconListEntry.type = entry->ie_FileInfoBlock->fib_DirEntryType;
4623 else
4625 if (message->entry->ie_FileInfoBlock)
4627 FreeMem(message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4628 message->entry->ie_FileInfoBlock = NULL;
4630 if (message->entry->ie_IconListEntry.type != ST_USERDIR)
4632 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4633 message->entry->ie_IconListEntry.type = ST_USERDIR;
4637 /* Override type if specified */
4638 if ((message->type != 0) && (message->entry->ie_IconListEntry.type != message->type))
4640 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4641 message->entry->ie_IconListEntry.type = message->type;
4642 D(bug("[IconList] %s: Overide Entry Type. New Type = %x\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.type));
4644 else
4646 D(bug("[IconList] %s: Entry Type = %x\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.type));
4649 IconList_GetIconAreaRectangle(obj, data, message->entry, &rect);
4651 return (IPTR)message->entry;
4655 ///DoWheelMove()
4656 static void DoWheelMove(struct IClass *CLASS, Object *obj, LONG wheelx, LONG wheely, UWORD qual)
4658 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4660 LONG newleft = data->icld_ViewX,
4661 newtop = data->icld_ViewY;
4663 /* Use horizontal scrolling if any of the following cases are true ...
4665 # vertical wheel is used but there's nothing to scroll
4666 (everything is visible already) ..
4668 # vertical wheel is used and one of the ALT keys is down. */
4670 if ((wheely && !wheelx) &&
4671 ((data->icld_AreaHeight <= _mheight(obj)) || (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))))
4673 wheelx = wheely; wheely = 0;
4676 if (qual & (IEQUALIFIER_CONTROL))
4678 if (wheelx < 0) newleft = 0;
4679 if (wheelx > 0) newleft = data->icld_AreaWidth;
4680 if (wheely < 0) newtop = 0;
4681 if (wheely > 0) newtop = data->icld_AreaHeight;
4683 else if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
4685 newleft += (wheelx * _mwidth(obj));
4686 newtop += (wheely * _mheight(obj));
4688 else
4690 newleft += wheelx * 30;
4691 newtop += wheely * 30;
4694 if (newleft + _mwidth(obj) > data->icld_AreaWidth)
4695 newleft = data->icld_AreaWidth - _mwidth(obj);
4696 if (newleft < 0)
4697 newleft = 0;
4699 if (newtop + _mheight(obj) > data->icld_AreaHeight)
4700 newtop = data->icld_AreaHeight - _mheight(obj);
4701 if (newtop < 0)
4702 newtop = 0;
4704 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
4706 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
4707 MUIA_Virtgroup_Top, newtop,
4708 TAG_DONE);
4713 /* Notes:
4715 * LEFTDOWN
4716 * a) if clicked object is selected, nothing
4717 * b) if clicked object is not selected, unselect all, select object
4718 * c) if no clicked object, start lasso
4719 * LEFTUP
4720 * a) if in lasso, finish lasso
4721 * LEFTDOWN + SHIFT
4722 * a) if object is selected, unselect it (= remove from multiselection)
4723 * b) if object is not selected, select it (= add to multiselection)
4726 * Expected behaviour:
4727 * a) you can only "remove" multiselection by clicking on not selected object or on space where there is no icon
4731 static void IconList_HandleNewIconSelection(struct IClass *CLASS, Object *obj, struct MUIP_HandleEvent *message,
4732 struct IconEntry *new_selected, BOOL *doubleclicked)
4734 struct IconEntry *node = NULL;
4735 BOOL update_entry = FALSE;
4736 LONG mx = message->imsg->MouseX - _mleft(obj);
4737 LONG my = message->imsg->MouseY - _mtop(obj);
4738 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4739 BOOL nounselection = (new_selected != NULL &&
4740 (new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED)); /* see notes above */
4743 /* Check if this is a double click on icon or empty space */
4744 if ((DoubleClick(data->last_secs, data->last_mics, message->imsg->Seconds, message->imsg->Micros)) && (data->icld_SelectionLastClicked == new_selected))
4746 #if defined(DEBUG_ILC_EVENTS)
4747 D(bug("[IconList] %s: Entry double-clicked\n", __PRETTY_FUNCTION__));
4748 #endif
4749 *doubleclicked = TRUE;
4752 /* Deselection lopp */
4753 #if defined(__AROS__)
4754 ForeachNode(&data->icld_IconList, node)
4755 #else
4756 Foreach_Node(&data->icld_IconList, node);
4757 #endif
4759 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4761 update_entry = FALSE;
4763 /* If node that is being checked is selected and it is not the clicked node
4764 * and no shift pressed and
4765 * clicked node is not part of selection (see notes above) or this is a double click */
4766 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
4768 if ((new_selected != node) &&
4769 (!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))) &&
4770 (!nounselection || *doubleclicked))
4772 Remove(&node->ie_SelectionNode);
4773 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
4774 update_entry = TRUE;
4778 /* Remove focus */
4779 if ((node->ie_Flags & ICONENTRY_FLAG_FOCUS) && (new_selected != node))
4781 node->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
4782 update_entry = TRUE;
4785 /* Redraw list */
4786 if (update_entry)
4788 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4789 data->update_entry = node;
4790 MUI_Redraw(obj, MADF_DRAWUPDATE);
4791 #if defined(DEBUG_ILC_EVENTS)
4792 D(bug("[IconList] %s: Rendered entry '%s'\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
4793 #endif
4798 if (new_selected != NULL)
4800 /* Found clicked entry... */
4801 data->icld_LassoActive = FALSE;
4802 update_entry = FALSE;
4804 if (!(new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED))
4806 /* Add new entry to selection */
4807 AddTail(&data->icld_SelectionList, &new_selected->ie_SelectionNode);
4808 new_selected->ie_Flags |= ICONENTRY_FLAG_SELECTED;
4809 update_entry = TRUE;
4811 else if ((*doubleclicked == FALSE) && (message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
4813 /* Unselect previously selected entry */
4814 Remove(&new_selected->ie_SelectionNode);
4815 new_selected->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
4816 update_entry = TRUE;
4819 /* Set focus */
4820 if (!(new_selected->ie_Flags & ICONENTRY_FLAG_FOCUS))
4822 new_selected->ie_Flags |= ICONENTRY_FLAG_FOCUS;
4823 data->icld_FocusIcon = new_selected;
4824 update_entry = TRUE;
4827 /* Redraw list */
4828 if (update_entry)
4830 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4831 data->update_entry = new_selected;
4832 MUI_Redraw(obj, MADF_DRAWUPDATE);
4833 #if defined(DEBUG_ILC_EVENTS)
4834 D(bug("[IconList] %s: Rendered 'new_selected' entry '%s'\n", __PRETTY_FUNCTION__, new_selected->ie_IconListEntry.label));
4835 #endif
4838 else
4840 struct Window * thisWindow = NULL;
4841 #if defined(DEBUG_ILC_EVENTS) || defined(DEBUG_ILC_LASSO)
4842 D(bug("[IconList] %s: Starting Lasso\n", __PRETTY_FUNCTION__));
4843 #endif
4844 /* No entry clicked on ... Start Lasso-selection */
4845 data->icld_LassoActive = TRUE;
4846 if (!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
4848 data->icld_SelectionLastClicked = NULL;
4849 data->icld_FocusIcon = NULL;
4851 data->icld_LassoRectangle.MinX = mx - data->view_rect.MinX + data->icld_ViewX;
4852 data->icld_LassoRectangle.MinY = my - data->view_rect.MinY + data->icld_ViewY;
4853 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
4854 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
4856 /* Draw initial Lasso frame */
4857 IconList_InvertLassoOutlines(obj, data, &data->icld_LassoRectangle);
4859 /* Start handling INTUITICKS */
4860 GET(obj, MUIA_Window, &thisWindow);
4861 if (thisWindow)
4863 ModifyIDCMP(thisWindow, (thisWindow->IDCMPFlags|IDCMP_INTUITICKS));
4864 if (!(data->ehn.ehn_Events & IDCMP_INTUITICKS))
4866 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
4867 data->ehn.ehn_Events |= IDCMP_INTUITICKS;
4868 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
4874 ///MUIM_HandleEvent()
4875 /**************************************************************************
4876 MUIM_HandleEvent
4877 **************************************************************************/
4878 IPTR IconList__MUIM_HandleEvent(struct IClass *CLASS, Object *obj, struct MUIP_HandleEvent *message)
4880 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4882 #if defined(DEBUG_ILC_FUNCS)
4883 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4884 #endif
4886 if (message->imsg)
4888 LONG mx = message->imsg->MouseX - _mleft(obj);
4889 LONG my = message->imsg->MouseY - _mtop(obj);
4891 LONG wheelx = 0;
4892 LONG wheely = 0;
4894 switch (message->imsg->Class)
4896 case IDCMP_NEWSIZE:
4897 bug("[IconList] %s: IDCMP_NEWSIZE\n", __PRETTY_FUNCTION__);
4898 break;
4900 case IDCMP_RAWKEY:
4902 #if defined(DEBUG_ILC_EVENTS)
4903 D(bug("[IconList] %s: IDCMP_RAWKEY\n", __PRETTY_FUNCTION__));
4904 #endif
4905 BOOL rawkey_handled = FALSE;
4907 switch(message->imsg->Code)
4909 case RAWKEY_NM_WHEEL_UP:
4910 wheely = -1;
4911 rawkey_handled = TRUE;
4912 break;
4914 case RAWKEY_NM_WHEEL_DOWN:
4915 wheely = 1;
4916 rawkey_handled = TRUE;
4917 break;
4919 case RAWKEY_NM_WHEEL_LEFT:
4920 wheelx = -1;
4921 rawkey_handled = TRUE;
4922 break;
4924 case RAWKEY_NM_WHEEL_RIGHT:
4925 wheelx = 1;
4926 rawkey_handled = TRUE;
4927 break;
4930 /* Remove the lasso if a key is pressed or the mouse wheel is used */
4931 NullifyLasso(data, obj);
4933 if (rawkey_handled)
4935 #if defined(DEBUG_ILC_KEYEVENTS)
4936 D(bug("[IconList] %s: Processing mouse wheel event\n", __PRETTY_FUNCTION__));
4937 #endif
4938 if (_isinobject(message->imsg->MouseX, message->imsg->MouseY) &&
4939 (wheelx || wheely))
4941 DoWheelMove(CLASS, obj, wheelx, wheely, message->imsg->Qualifier);
4944 else if (!(message->imsg->Code & IECODE_UP_PREFIX))
4946 LONG new_ViewY = data->icld_ViewY;
4947 struct IconEntry *start_entry = NULL, *active_entry = NULL, *entry_next = NULL;
4948 IPTR start_X = 0, start_Y = 0, active_X = 0, active_Y = 0, next_X = 0, next_Y = 0;
4949 IPTR x_diff = 0;
4951 #if defined(DEBUG_ILC_KEYEVENTS)
4952 D(bug("[IconList] %s: Processing key up event\n", __PRETTY_FUNCTION__));
4953 #endif
4955 switch(message->imsg->Code)
4957 case RAWKEY_RETURN:
4958 rawkey_handled = TRUE;
4960 #if defined(DEBUG_ILC_KEYEVENTS)
4961 D(bug("[IconList] %s: RAWKEY_RETURN\n", __PRETTY_FUNCTION__));
4962 #endif
4964 if (data->icld_FocusIcon) active_entry = data->icld_FocusIcon;
4965 else if (data->icld_SelectionLastClicked) active_entry = data->icld_SelectionLastClicked;
4967 if (active_entry)
4969 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
4971 active_entry->ie_Flags |= ICONENTRY_FLAG_SELECTED;
4972 AddTail(&data->icld_SelectionList, &active_entry->ie_SelectionNode);
4973 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4974 data->update_entry = active_entry;
4975 MUI_Redraw(obj, MADF_DRAWUPDATE);
4977 data->icld_SelectionLastClicked = active_entry;
4978 data->icld_FocusIcon = active_entry;
4980 SET(obj, MUIA_IconList_DoubleClick, TRUE);
4982 break;
4984 case RAWKEY_SPACE:
4985 rawkey_handled = TRUE;
4987 #if defined(DEBUG_ILC_KEYEVENTS)
4988 D(bug("[IconList] %s: RAWKEY_SPACE\n", __PRETTY_FUNCTION__));
4989 #endif
4991 if (data->icld_FocusIcon) active_entry = data->icld_FocusIcon;
4992 else if (data->icld_SelectionLastClicked) active_entry = data->icld_SelectionLastClicked;
4994 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)||(data->icld_SelectionLastClicked != active_entry)))
4996 #if defined(DEBUG_ILC_KEYEVENTS)
4997 D(bug("[IconList] %s: SPACE: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
4998 #endif
4999 DoMethod(obj, MUIM_IconList_UnselectAll);
5002 if (active_entry)
5004 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
5006 AddTail(&data->icld_SelectionList, &active_entry->ie_SelectionNode);
5007 active_entry->ie_Flags |= ICONENTRY_FLAG_SELECTED;
5008 data->icld_SelectionLastClicked = active_entry;
5010 else
5012 Remove(&active_entry->ie_SelectionNode);
5013 active_entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
5016 data->icld_FocusIcon = active_entry;
5018 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5019 data->update_entry = active_entry;
5020 MUI_Redraw(obj, MADF_DRAWUPDATE);
5022 break;
5024 case RAWKEY_PAGEUP:
5025 rawkey_handled = TRUE;
5027 #if defined(DEBUG_ILC_KEYEVENTS)
5028 D(bug("[IconList] %s: RAWKEY_PAGEUP\n", __PRETTY_FUNCTION__));
5029 #endif
5031 if (data->icld_AreaHeight > data->icld_ViewHeight)
5033 new_ViewY -= data->icld_ViewHeight;
5034 if (new_ViewY< 0)
5035 new_ViewY = 0;
5038 if (new_ViewY != data->icld_ViewY)
5040 SET(obj, MUIA_Virtgroup_Top, new_ViewY);
5042 break;
5044 case RAWKEY_PAGEDOWN:
5045 rawkey_handled = TRUE;
5047 #if defined(DEBUG_ILC_KEYEVENTS)
5048 D(bug("[IconList] %s: RAWKEY_PAGEDOWN\n", __PRETTY_FUNCTION__));
5049 #endif
5051 if (data->icld_AreaHeight > data->icld_ViewHeight)
5053 new_ViewY += data->icld_ViewHeight;
5054 if (new_ViewY > (data->icld_AreaHeight - data->icld_ViewHeight))
5055 new_ViewY = data->icld_AreaHeight - data->icld_ViewHeight;
5058 if (new_ViewY != data->icld_ViewY)
5060 SET(obj, MUIA_Virtgroup_Top, new_ViewY);
5062 break;
5064 case RAWKEY_UP:
5065 rawkey_handled = TRUE;
5067 #if defined(DEBUG_ILC_KEYEVENTS)
5068 D(bug("[IconList] %s: RAWKEY_UP\n", __PRETTY_FUNCTION__));
5069 #endif
5071 if (data->icld_FocusIcon)
5073 start_entry = data->icld_FocusIcon;
5074 #if defined(DEBUG_ILC_KEYEVENTS)
5075 D(bug("[IconList] %s: UP: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5076 #endif
5078 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5079 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5080 data->update_entry = start_entry;
5081 MUI_Redraw(obj, MADF_DRAWUPDATE);
5083 start_X = start_entry->ie_IconX;
5084 start_Y = start_entry->ie_IconY;
5085 #if defined(DEBUG_ILC_KEYEVENTS)
5086 D(bug("[IconList] %s: UP: start_icon @ 0x%p '%s' - start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_entry, start_entry->ie_IconListEntry.label, start_X, start_Y));
5087 #endif
5088 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5090 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5092 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5093 #if defined(DEBUG_ILC_KEYEVENTS)
5094 D(bug("[IconList] %s: UP: adjusted start_X for grid = %d\n", __PRETTY_FUNCTION__, start_X));
5095 #endif
5099 if ((active_entry = Node_PreviousVisible(start_entry)) && !(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5101 //Check if we are at the edge of the entry area ..
5102 #if defined(DEBUG_ILC_KEYEVENTS)
5103 D(bug("[IconList] %s: UP: active_entry @ 0x%p '%s' , X %d, Y %d\n", __PRETTY_FUNCTION__, active_entry, active_entry->ie_IconListEntry.label, active_entry->ie_IconX, active_entry->ie_IconY));
5104 #endif
5105 active_Y = active_entry->ie_IconY;
5107 if (active_Y == start_Y)
5110 #if defined(DEBUG_ILC_KEYEVENTS)
5111 D(bug("[IconList] %s: UP: active_entry is on our row (not at the edge)\n", __PRETTY_FUNCTION__));
5112 #endif
5113 entry_next = active_entry;
5114 next_X = entry_next->ie_IconX;
5115 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5117 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5118 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5122 #if defined(DEBUG_ILC_KEYEVENTS)
5123 D(bug("[IconList] %s: UP: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5124 #endif
5127 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5129 #if defined(DEBUG_ILC_KEYEVENTS)
5130 D(bug("[IconList] %s: UP: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5131 #endif
5132 DoMethod(obj, MUIM_IconList_UnselectAll);
5135 #if defined(DEBUG_ILC_KEYEVENTS)
5136 D(bug("[IconList] %s: UP: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5137 #endif
5138 if (!(active_entry))
5140 // If nothing is selected we will use the last visible entry ..
5141 active_entry = Node_LastVisible(&data->icld_IconList);
5142 start_X = active_entry->ie_IconX;
5143 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5145 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5146 start_X = start_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5148 start_Y = active_entry->ie_IconY;
5151 while (active_entry != NULL)
5153 #if defined(DEBUG_ILC_KEYEVENTS)
5154 D(bug("[IconList] %s: UP: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5155 #endif
5156 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
5158 // Return the first visible since the list flow direction matches
5159 // our cursor direction
5160 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5161 break;
5163 else
5165 active_X = active_entry->ie_IconX;
5167 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5169 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5170 x_diff = ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5172 active_Y = active_entry->ie_IconY;
5174 if (start_entry)
5176 if (entry_next)
5178 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5179 (active_Y < start_Y) &&
5180 (((active_X - x_diff) >= start_X ) &&
5181 ((active_X - x_diff) <= (start_X + start_entry->ie_AreaWidth + (x_diff*2)))))
5183 #if defined(DEBUG_ILC_KEYEVENTS)
5184 D(bug("[IconList] %s: UP: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5185 #endif
5186 break;
5188 else if (active_entry == (struct IconEntry *)GetHead(&data->icld_IconList))
5190 #if defined(DEBUG_ILC_KEYEVENTS)
5191 D(bug("[IconList] %s: UP: (A) reached list start .. restarting from the end ..\n", __PRETTY_FUNCTION__));
5192 #endif
5193 start_X = next_X;
5195 if ((entry_next = Node_PreviousVisible(entry_next)))
5197 if (entry_next->ie_IconX > start_X)
5198 entry_next = NULL;
5199 else
5201 next_X = entry_next->ie_IconX;
5202 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5204 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5205 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5209 start_Y = 0;
5210 #if defined(DEBUG_ILC_KEYEVENTS)
5211 D(bug("[IconList] %s: UP: (A) startx = %d, start_Y = %d, next_X = %d, entry_next @ 0x%p\n", __PRETTY_FUNCTION__, start_X, start_Y, next_X, entry_next));
5212 #endif
5213 active_entry = Node_LastVisible(&data->icld_IconList);
5216 else
5218 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5219 (active_Y < start_Y) &&
5220 ((active_X + x_diff) < (start_X + start_entry->ie_AreaWidth + x_diff)))
5222 #if defined(DEBUG_ILC_KEYEVENTS)
5223 D(bug("[IconList] %s: UP: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5224 #endif
5225 break;
5229 else
5231 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5233 #if defined(DEBUG_ILC_KEYEVENTS)
5234 D(bug("[IconList] %s: UP: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5235 #endif
5236 break;
5240 active_entry = (struct IconEntry *)(((struct Node *)active_entry)->ln_Pred);
5243 if (!(active_entry))
5245 #if defined(DEBUG_ILC_KEYEVENTS)
5246 D(bug("[IconList] %s: UP: No Next UP Node - Getting Last visible entry ..\n", __PRETTY_FUNCTION__));
5247 #endif
5248 /* We didnt find a "next UP" entry so just use the last visible */
5249 active_entry = Node_LastVisible(&data->icld_IconList);
5252 if (active_entry)
5254 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5256 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5257 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5258 data->update_entry = active_entry;
5259 MUI_Redraw(obj, MADF_DRAWUPDATE);
5262 data->icld_FocusIcon = active_entry;
5263 break;
5265 case RAWKEY_DOWN:
5266 rawkey_handled = TRUE;
5268 #if defined(DEBUG_ILC_KEYEVENTS)
5269 D(bug("[IconList] %s: RAWKEY_DOWN\n", __PRETTY_FUNCTION__));
5270 #endif
5271 if (data->icld_FocusIcon)
5273 start_entry = data->icld_FocusIcon;
5274 #if defined(DEBUG_ILC_KEYEVENTS)
5275 D(bug("[IconList] %s: DOWN: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5276 #endif
5278 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5279 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5280 data->update_entry = start_entry;
5281 MUI_Redraw(obj, MADF_DRAWUPDATE);
5283 start_X = start_entry->ie_IconX;
5284 start_Y = start_entry->ie_IconY;
5285 #if defined(DEBUG_ILC_KEYEVENTS)
5286 D(bug("[IconList] %s: DOWN: start_icon @ 0x%p '%s' - start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_entry, start_entry->ie_IconListEntry.label, start_X, start_Y));
5287 #endif
5288 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5290 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5292 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5293 #if defined(DEBUG_ILC_KEYEVENTS)
5294 D(bug("[IconList] %s: DOWN: adjusted start_X for grid = %d\n", __PRETTY_FUNCTION__, start_X));
5295 #endif
5299 if ((active_entry = Node_NextVisible(start_entry)) &&
5300 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5302 #if defined(DEBUG_ILC_KEYEVENTS)
5303 D(bug("[IconList] %s: DOWN: active_entry @ 0x%p '%s' , X %d, Y %d\n", __PRETTY_FUNCTION__, active_entry, active_entry->ie_IconListEntry.label, active_entry->ie_IconX, active_entry->ie_IconY));
5304 #endif
5305 active_Y = active_entry->ie_IconY;
5307 if (active_Y == start_Y)
5310 #if defined(DEBUG_ILC_KEYEVENTS)
5311 D(bug("[IconList] %s: DOWN: active_entry is on our row (not at the edge)\n", __PRETTY_FUNCTION__));
5312 #endif
5313 entry_next = active_entry;
5314 next_X = entry_next->ie_IconX;
5315 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5317 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5318 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5322 #if defined(DEBUG_ILC_KEYEVENTS)
5323 D(bug("[IconList] %s: DOWN: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5324 #endif
5327 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5329 #if defined(DEBUG_ILC_KEYEVENTS)
5330 D(bug("[IconList] %s: DOWN: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5331 #endif
5332 DoMethod(obj, MUIM_IconList_UnselectAll);
5335 #if defined(DEBUG_ILC_KEYEVENTS)
5336 D(bug("[IconList] %s: DOWN: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5337 #endif
5338 if (!(active_entry))
5340 // If nothing is selected we will use the First visible entry ..
5341 active_entry = Node_FirstVisible(&data->icld_IconList);
5342 start_X = active_entry->ie_IconX;
5343 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5345 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5346 start_X = start_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5348 start_Y = active_entry->ie_IconY;
5351 while (active_entry != NULL)
5353 #if defined(DEBUG_ILC_KEYEVENTS)
5354 D(bug("[IconList] %s: DOWN: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5355 #endif
5356 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
5358 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5359 break;
5361 else
5363 active_X = active_entry->ie_IconX;
5365 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5367 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5368 x_diff = ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5370 active_Y = active_entry->ie_IconY;
5372 if (start_entry)
5374 if (entry_next)
5376 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5377 (active_Y > start_Y) &&
5378 (((active_X - x_diff) >= start_X ) &&
5379 ((active_X - x_diff) <= (start_X + start_entry->ie_AreaWidth + (x_diff*2)))))
5381 #if defined(DEBUG_ILC_KEYEVENTS)
5382 D(bug("[IconList] %s: DOWN: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5383 #endif
5384 break;
5386 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
5388 #if defined(DEBUG_ILC_KEYEVENTS)
5389 D(bug("[IconList] %s: DOWN: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
5390 #endif
5391 start_X = entry_next->ie_IconX;
5392 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5394 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5395 start_X = start_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5398 if ((entry_next = (struct IconEntry *)Node_NextVisible(entry_next)))
5400 if (entry_next->ie_IconX < start_X)
5401 entry_next = NULL;
5402 else
5404 next_X = entry_next->ie_IconX;
5405 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5407 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5408 next_X = next_X + ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5412 start_Y = 0;
5413 #if defined(DEBUG_ILC_KEYEVENTS)
5414 D(bug("[IconList] %s: DOWN: (A) startx = %d, start_Y = %d, next_X = %d, entry_next @ 0x%p\n", __PRETTY_FUNCTION__, start_X, start_Y, next_X, entry_next));
5415 #endif
5416 active_entry = Node_FirstVisible(&data->icld_IconList);
5419 else
5421 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5422 (active_Y > start_Y) &&
5423 (active_X > start_X - 1))
5425 #if defined(DEBUG_ILC_KEYEVENTS)
5426 D(bug("[IconList] %s: DOWN: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5427 #endif
5428 break;
5432 else
5434 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5436 #if defined(DEBUG_ILC_KEYEVENTS)
5437 D(bug("[IconList] %s: DOWN: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5438 #endif
5439 break;
5443 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5446 if (!(active_entry))
5448 #if defined(DEBUG_ILC_KEYEVENTS)
5449 D(bug("[IconList] %s: DOWN: No Next DOWN Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
5450 #endif
5451 /* We didnt find a "next DOWN" entry so just use the first visible */
5452 active_entry = Node_FirstVisible(&data->icld_IconList);
5455 if (active_entry)
5457 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5459 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5460 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5461 data->update_entry = active_entry;
5462 MUI_Redraw(obj, MADF_DRAWUPDATE);
5465 data->icld_FocusIcon = active_entry;
5466 break;
5468 case RAWKEY_LEFT:
5469 rawkey_handled = TRUE;
5471 #if defined(DEBUG_ILC_KEYEVENTS)
5472 D(bug("[IconList] %s: RAWKEY_LEFT\n", __PRETTY_FUNCTION__));
5473 #endif
5474 if (data->icld_FocusIcon)
5476 start_entry = data->icld_FocusIcon;
5477 #if defined(DEBUG_ILC_KEYEVENTS)
5478 D(bug("[IconList] %s: LEFT: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5479 #endif
5481 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5482 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5483 data->update_entry = start_entry;
5484 MUI_Redraw(obj, MADF_DRAWUPDATE);
5486 start_X = start_entry->ie_IconX;
5487 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5489 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5490 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5492 start_Y = start_entry->ie_IconY;
5494 #if defined(DEBUG_ILC_KEYEVENTS)
5495 D(bug("[IconList] %s: LEFT: start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5496 #endif
5498 if (!(active_entry = Node_NextVisible(start_entry)) && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5500 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5501 #if defined(DEBUG_ILC_KEYEVENTS)
5502 D(bug("[IconList] %s: LEFT: Start at the beginning (Active @ 0x%p) using entry X + Width\n", __PRETTY_FUNCTION__, active_entry));
5503 #endif
5504 start_X = start_X + start_entry->ie_AreaWidth;
5505 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5507 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5508 start_X = start_X + ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5511 start_Y = 0;
5512 entry_next = NULL;
5514 else if (active_entry && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5516 #if defined(DEBUG_ILC_KEYEVENTS)
5517 D(bug("[IconList] %s: LEFT: Active @ 0x%p, X %d\n", __PRETTY_FUNCTION__, active_entry, active_entry->ie_IconX));
5518 #endif
5519 if ((entry_next = Node_NextVisible(start_entry)))
5521 #if defined(DEBUG_ILC_KEYEVENTS)
5522 D(bug("[IconList] %s: LEFT: Next @ 0x%p, X %d\n", __PRETTY_FUNCTION__, entry_next, entry_next->ie_IconX));
5523 #endif
5525 if (entry_next->ie_IconX < start_X)
5526 entry_next = NULL;
5527 else
5529 next_X = entry_next->ie_IconX;
5530 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5532 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5533 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5538 #if defined(DEBUG_ILC_KEYEVENTS)
5539 D(bug("[IconList] %s: LEFT: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5540 #endif
5543 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5545 #if defined(DEBUG_ILC_KEYEVENTS)
5546 D(bug("[IconList] %s: LEFT: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5547 #endif
5548 DoMethod(obj, MUIM_IconList_UnselectAll);
5551 #if defined(DEBUG_ILC_KEYEVENTS)
5552 D(bug("[IconList] %s: LEFT: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5553 #endif
5555 if (!(active_entry))
5557 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5560 while (active_entry != NULL)
5562 #if defined(DEBUG_ILC_KEYEVENTS)
5563 D(bug("[IconList] %s: LEFT: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5564 #endif
5565 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
5567 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5568 break;
5570 else
5572 LONG active_entry_X = active_entry->ie_IconX;
5573 LONG active_entry_Y;
5574 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5576 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5577 active_entry_X = active_entry_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5579 active_entry_Y = active_entry->ie_IconY;
5581 if (start_entry)
5583 if (entry_next)
5585 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5586 (active_entry_Y > start_Y) &&
5587 ((active_entry_X > start_X - 1) &&
5588 (active_entry_X < next_X)))
5590 #if defined(DEBUG_ILC_KEYEVENTS)
5591 D(bug("[IconList] %s: LEFT: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5592 #endif
5593 break;
5595 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
5597 #if defined(DEBUG_ILC_KEYEVENTS)
5598 D(bug("[IconList] %s: LEFT: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
5599 #endif
5600 start_X = entry_next->ie_IconX;
5601 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5603 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5604 start_X = start_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5607 if ((entry_next = Node_NextVisible(entry_next)))
5609 if (entry_next->ie_IconX < start_X)
5610 entry_next = NULL;
5611 else
5613 next_X = entry_next->ie_IconX;
5614 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5616 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5617 next_X = next_X + ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5621 start_Y = 0;
5622 #if defined(DEBUG_ILC_KEYEVENTS)
5623 D(bug("[IconList] %s: LEFT: (A) startx = %d, start_Y = %d, next_X = %d, entry_next @ 0x%p\n", __PRETTY_FUNCTION__, start_X, start_Y, next_X, entry_next));
5624 #endif
5625 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5628 else
5630 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5631 (active_entry_Y > start_Y) &&
5632 (active_entry_X > start_X - 1))
5634 #if defined(DEBUG_ILC_KEYEVENTS)
5635 D(bug("[IconList] %s: LEFT: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5636 #endif
5637 break;
5641 else
5643 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5645 #if defined(DEBUG_ILC_KEYEVENTS)
5646 D(bug("[IconList] %s: LEFT: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5647 #endif
5648 break;
5652 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5655 if (!(active_entry))
5657 #if defined(DEBUG_ILC_KEYEVENTS)
5658 D(bug("[IconList] %s: LEFT: No Next LEFT Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
5659 #endif
5660 /* We didnt find a "next LEFT" entry so just use the last visible */
5661 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5662 while ((active_entry != NULL) &&(!(active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
5664 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5668 if (active_entry)
5670 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5672 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5673 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5674 data->update_entry = active_entry;
5675 MUI_Redraw(obj, MADF_DRAWUPDATE);
5678 data->icld_FocusIcon = active_entry;
5679 break;
5681 case RAWKEY_RIGHT:
5682 rawkey_handled = TRUE;
5684 #if defined(DEBUG_ILC_KEYEVENTS)
5685 D(bug("[IconList] %s: RAWKEY_RIGHT\n", __PRETTY_FUNCTION__));
5686 #endif
5688 if (data->icld_FocusIcon)
5690 start_entry = data->icld_FocusIcon;
5691 #if defined(DEBUG_ILC_KEYEVENTS)
5692 D(bug("[IconList] %s: RIGHT: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5693 #endif
5694 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5695 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5696 data->update_entry = start_entry;
5697 MUI_Redraw(obj, MADF_DRAWUPDATE);
5699 start_X = start_entry->ie_IconX;
5700 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5702 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5703 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5705 start_Y = start_entry->ie_IconY;
5707 #if defined(DEBUG_ILC_KEYEVENTS)
5708 D(bug("[IconList] %s: RIGHT: start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5709 #endif
5710 if (!(active_entry = Node_NextVisible(start_entry)) && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5712 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5713 #if defined(DEBUG_ILC_KEYEVENTS)
5714 D(bug("[IconList] %s: RIGHT: Start at the beginning (Active @ 0x%p) using entry X + Width\n", __PRETTY_FUNCTION__, active_entry));
5715 #endif
5716 start_X = 0;
5717 start_Y = start_Y + start_entry->ie_AreaHeight;
5718 entry_next = NULL;
5720 else if (active_entry && (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5722 #if defined(DEBUG_ILC_KEYEVENTS)
5723 D(bug("[IconList] %s: RIGHT: Active @ 0x%p, X %d\n", __PRETTY_FUNCTION__, active_entry, active_entry->ie_IconX));
5724 #endif
5725 if ((entry_next = Node_NextVisible(start_entry)))
5727 #if defined(DEBUG_ILC_KEYEVENTS)
5728 D(bug("[IconList] %s: RIGHT: Next @ 0x%p, X %d\n", __PRETTY_FUNCTION__, entry_next, entry_next->ie_IconX));
5729 #endif
5731 if (entry_next->ie_IconY < start_Y)
5732 entry_next = NULL;
5733 else
5734 next_Y = entry_next->ie_IconY;
5737 #if defined(DEBUG_ILC_KEYEVENTS)
5738 D(bug("[IconList] %s: RIGHT: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5739 #endif
5742 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5744 #if defined(DEBUG_ILC_KEYEVENTS)
5745 D(bug("[IconList] %s: RIGHT: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5746 #endif
5747 DoMethod(obj, MUIM_IconList_UnselectAll);
5750 #if defined(DEBUG_ILC_KEYEVENTS)
5751 D(bug("[IconList] %s: RIGHT: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5752 #endif
5754 if (!(active_entry))
5756 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5759 while (active_entry != NULL)
5761 #if defined(DEBUG_ILC_KEYEVENTS)
5762 D(bug("[IconList] %s: RIGHT: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5763 #endif
5764 if (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5766 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5767 break;
5769 else
5771 LONG active_entry_X = active_entry->ie_IconX;
5772 LONG active_entry_Y;
5773 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5775 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5776 active_entry_X = active_entry_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5778 active_entry_Y = active_entry->ie_IconY;
5780 if (start_entry)
5782 if (entry_next)
5784 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5785 (active_entry_X > start_X) &&
5786 ((active_entry_Y > start_Y - 1) &&
5787 (active_entry_Y < next_Y)))
5789 #if defined(DEBUG_ILC_KEYEVENTS)
5790 D(bug("[IconList] %s: RIGHT: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5791 #endif
5792 break;
5794 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
5796 #if defined(DEBUG_ILC_KEYEVENTS)
5797 D(bug("[IconList] %s: RIGHT: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
5798 #endif
5799 start_Y = entry_next->ie_IconY;
5801 if ((entry_next = Node_NextVisible(entry_next)))
5803 if (entry_next->ie_IconY < start_Y)
5804 entry_next = NULL;
5805 else
5807 next_Y = entry_next->ie_IconY;
5810 start_Y = 0;
5811 #if defined(DEBUG_ILC_KEYEVENTS)
5812 D(bug("[IconList] %s: RIGHT: (A) startx = %d, start_Y = %d, next_X = %d, entry_next @ 0x%p\n", __PRETTY_FUNCTION__, start_X, start_Y, next_X, entry_next));
5813 #endif
5814 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5817 else
5819 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5820 (active_entry_X > start_X) &&
5821 (active_entry_Y > start_Y - 1))
5823 #if defined(DEBUG_ILC_KEYEVENTS)
5824 D(bug("[IconList] %s: RIGHT: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5825 #endif
5826 break;
5830 else
5832 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5834 #if defined(DEBUG_ILC_KEYEVENTS)
5835 D(bug("[IconList] %s: RIGHT: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5836 #endif
5837 break;
5841 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5844 if (!(active_entry))
5846 #if defined(DEBUG_ILC_KEYEVENTS)
5847 D(bug("[IconList] %s: RIGHT: No Next RIGHT Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
5848 #endif
5849 /* We didnt find a "next RIGHT" entry so just use the first visible */
5850 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5851 while ((active_entry != NULL) &&(!(active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
5853 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5857 if (active_entry)
5859 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5861 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5862 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5863 data->update_entry = active_entry;
5864 MUI_Redraw(obj, MADF_DRAWUPDATE);
5867 data->icld_FocusIcon = active_entry;
5868 break;
5870 case RAWKEY_HOME:
5871 rawkey_handled = TRUE;
5873 #if defined(DEBUG_ILC_KEYEVENTS)
5874 D(bug("[IconList] %s: RAWKEY_HOME\n", __PRETTY_FUNCTION__));
5875 #endif
5877 if (data->icld_FocusIcon)
5879 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5880 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5881 data->update_entry = data->icld_FocusIcon;
5882 MUI_Redraw(obj, MADF_DRAWUPDATE);
5885 active_entry = Node_FirstVisible(&data->icld_IconList);
5887 if ((active_entry) && (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
5889 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5890 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5891 data->update_entry = active_entry;
5892 MUI_Redraw(obj, MADF_DRAWUPDATE);
5894 data->icld_FocusIcon = active_entry;
5895 break;
5897 case RAWKEY_END:
5898 rawkey_handled = TRUE;
5900 #if defined(DEBUG_ILC_KEYEVENTS)
5901 D(bug("[IconList] %s: RAWKEY_END\n", __PRETTY_FUNCTION__));
5902 #endif
5904 if (data->icld_FocusIcon)
5906 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5907 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5908 data->update_entry = data->icld_FocusIcon;
5909 MUI_Redraw(obj, MADF_DRAWUPDATE);
5912 active_entry = Node_LastVisible(&data->icld_IconList);
5914 if ((active_entry) && (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
5916 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5917 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5918 data->update_entry = active_entry;
5919 MUI_Redraw(obj, MADF_DRAWUPDATE);
5921 data->icld_FocusIcon = active_entry;
5922 break;
5925 if (rawkey_handled) return MUI_EventHandlerRC_Eat;
5927 break;
5929 case IDCMP_MOUSEBUTTONS:
5930 #if defined(DEBUG_ILC_EVENTS)
5931 D(bug("[IconList] %s: IDCMP_MOUSEBUTTONS\n", __PRETTY_FUNCTION__));
5932 #endif
5933 if (message->imsg->Code == SELECTDOWN)
5935 /* Check if mouse pressed on iconlist area */
5936 if (mx >= 0 && mx < _width(obj) && my >= 0 && my < _height(obj))
5938 BOOL doubleclicked = FALSE; /* both icon and empty space */
5939 struct IconEntry *node = NULL;
5940 struct IconEntry *new_selected = NULL;
5942 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
5944 /* LIST-VIEW HANDLING */
5946 LONG clickColumn = -1;
5948 LONG x = _mleft(obj) - data->icld_ViewX + LINE_SPACING_LEFT;
5949 LONG index, w, i;
5951 /* Find column in which click happened */
5952 for(i = 0; i < NUM_COLUMNS; i++)
5954 index = data->icld_LVMAttribs->lmva_ColumnPos[i];
5956 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
5958 w = data->icld_LVMAttribs->lmva_ColumnWidth[index];
5960 if ((mx >= x) && (mx < x + w))
5962 clickColumn = index;
5963 break;
5965 x += w;
5968 if (((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0) && (my <= data->icld_LVMAttribs->lmva_HeaderHeight))
5970 /* Click on header, update list */
5971 data->icld_LVMAttribs->lmva_LastSelectedColumn = clickColumn;
5973 data->icld_UpdateMode = UPDATE_HEADERENTRY;
5974 data->update_entry = (APTR)(IPTR)clickColumn;
5976 MUI_Redraw(obj, MADF_DRAWUPDATE);
5979 else
5981 LONG current = 0, index = (my - data->icld_LVMAttribs->lmva_HeaderHeight + data->icld_ViewY) / data->icld_LVMAttribs->lmva_RowHeight;
5983 /* Check if clicked on entry */
5984 ForeachNode(&data->icld_IconList, node)
5986 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5988 /* Is this node clicked? */
5989 if (current == index)
5991 new_selected = node;
5992 break;
5995 current++;
5999 /* Handle actions */
6000 IconList_HandleNewIconSelection(CLASS, obj, message, new_selected, &doubleclicked);
6003 else
6005 /* ICON-VIEW HANDLING */
6007 struct Rectangle rect;
6009 /* Check if clicked on entry */
6010 #if defined(__AROS__)
6011 ForeachNode(&data->icld_IconList, node)
6012 #else
6013 Foreach_Node(&data->icld_IconList, node);
6014 #endif
6016 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6018 /* Is this node clicked? */
6019 rect.MinX = node->ie_IconX;
6020 rect.MaxX = node->ie_IconX + node->ie_AreaWidth - 1;
6021 rect.MinY = node->ie_IconY;
6022 rect.MaxY = node->ie_IconY + node->ie_AreaHeight - 1;
6024 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
6025 (node->ie_AreaWidth < data->icld_IconAreaLargestWidth))
6027 rect.MinX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
6028 rect.MaxX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
6031 if ((((mx + data->icld_ViewX) >= rect.MinX) && ((mx + data->icld_ViewX) <= rect.MaxX )) &&
6032 (((my + data->icld_ViewY) >= rect.MinY) && ((my + data->icld_ViewY) <= rect.MaxY )))
6034 new_selected = node;
6035 #if defined(DEBUG_ILC_EVENTS)
6036 D(bug("[IconList] %s: Entry '%s' clicked on ..\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
6037 #endif
6038 break;
6043 /* Handle actions */
6044 IconList_HandleNewIconSelection(CLASS, obj, message, new_selected, &doubleclicked);
6047 if (new_selected && (new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED))
6048 data->icld_SelectionLastClicked = new_selected;
6049 else
6050 data->icld_SelectionLastClicked = NULL;
6052 data->click_x = mx;
6053 data->click_y = my;
6055 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
6057 data->icld_ClickEvent.shift = !!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT));
6058 data->icld_ClickEvent.entry = data->icld_SelectionLastClicked ? &data->icld_SelectionLastClicked->ie_IconListEntry : NULL;
6059 SET(obj, MUIA_IconList_Clicked, (IPTR)&data->icld_ClickEvent);
6061 if (doubleclicked)
6063 SET(obj, MUIA_IconList_DoubleClick, TRUE);
6066 if ((!data->mouse_pressed) &&
6067 (!doubleclicked || (doubleclicked && (data->icld_SelectionLastClicked == NULL))))
6069 data->last_secs = message->imsg->Seconds;
6070 data->last_mics = message->imsg->Micros;
6072 /* After a double click you often open a new window
6073 * and since Zune doesn't not support the faking
6074 * of SELECTUP events only change the Events
6075 * if not doubleclicked on an icon */
6077 data->mouse_pressed |= LEFT_BUTTON;
6079 /* Start listening to mouse events */
6080 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
6082 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6083 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
6084 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6088 return MUI_EventHandlerRC_Eat;
6091 else if (message->imsg->Code == MIDDLEDOWN)
6093 if (!data->mouse_pressed)
6095 data->mouse_pressed |= MIDDLE_BUTTON;
6097 data->click_x = data->icld_ViewX + mx;
6098 data->click_y = data->icld_ViewY + my;
6100 /* Start listening to mouse events */
6101 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
6103 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6104 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
6105 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6109 else
6111 if (message->imsg->Code == SELECTUP)
6113 if (data->icld_LassoActive == TRUE)
6115 NullifyLasso(data, obj);
6117 else if (data->icld_LVMAttribs->lmva_LastSelectedColumn != -1)
6119 ULONG orig_sortflags = data->icld_SortFlags;
6121 if (data->icld_LVMAttribs->lmva_SortColumn == data->icld_LVMAttribs->lmva_LastSelectedColumn)
6123 if (data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
6124 data->icld_SortFlags &= ~MUIV_IconList_Sort_Reverse;
6125 else
6126 data->icld_SortFlags |= MUIV_IconList_Sort_Reverse;
6129 switch (data->icld_LVMAttribs->lmva_LastSelectedColumn)
6131 case INDEX_NAME:
6132 data->icld_SortFlags &= ~MUIV_IconList_Sort_Orders;
6133 data->icld_SortFlags |= MUIV_IconList_Sort_ByName;
6134 break;
6136 case INDEX_SIZE:
6137 data->icld_SortFlags &= ~MUIV_IconList_Sort_Orders;
6138 data->icld_SortFlags |= MUIV_IconList_Sort_BySize;
6139 break;
6141 case INDEX_LASTACCESS:
6142 data->icld_SortFlags &= ~MUIV_IconList_Sort_Orders;
6143 data->icld_SortFlags |= MUIV_IconList_Sort_ByDate;
6144 break;
6147 if (orig_sortflags != data->icld_SortFlags)
6149 data->icld_LVMAttribs->lmva_SortColumn = data->icld_LVMAttribs->lmva_LastSelectedColumn;
6151 data->icld_LVMAttribs->lmva_LastSelectedColumn = -1;
6153 DoMethod(obj, MUIM_IconList_Sort);
6157 data->mouse_pressed &= ~LEFT_BUTTON;
6160 if (message->imsg->Code == MIDDLEUP)
6162 data->mouse_pressed &= ~MIDDLE_BUTTON;
6165 /* Stop listening to mouse move events is no buttons pressed */
6166 if ((data->ehn.ehn_Events & IDCMP_MOUSEMOVE) && !data->mouse_pressed)
6168 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6169 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
6170 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6173 break;
6175 case IDCMP_INTUITICKS:
6177 #if defined(DEBUG_ILC_EVENTS)
6178 D(bug("[IconList] %s: IDCMP_INTUITICKS (%d, %d)\n", __PRETTY_FUNCTION__, mx, my));
6179 #endif
6180 if ((data->icld_LassoActive == FALSE)||(!(data->mouse_pressed & LEFT_BUTTON)))
6182 break;
6184 if (((mx >= 0) && (mx <= _mwidth(obj))) &&
6185 ((my >= 0) && (my <= _mheight(obj))))
6186 break;
6189 case IDCMP_MOUSEMOVE:
6190 #if defined(DEBUG_ILC_EVENTS)
6191 D(bug("[IconList] %s: IDCMP_MOUSEMOVE\n", __PRETTY_FUNCTION__));
6192 #endif
6193 if (data->mouse_pressed & LEFT_BUTTON)
6195 LONG move_x = mx;
6196 LONG move_y = my;
6198 if (data->icld_SelectionLastClicked && (data->icld_LassoActive == FALSE) &&
6199 ((abs(move_x - data->click_x) >= 2) || (abs(move_y - data->click_y) >= 2)))
6201 LONG touch_x, touch_y;
6203 /* Entry(s) being dragged .... */
6204 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6205 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
6206 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6208 data->mouse_pressed &= ~LEFT_BUTTON;
6210 /* Pass view relative coords */
6211 touch_x = move_x + data->icld_ViewX;
6212 touch_y = move_y + data->icld_ViewY;
6213 DoMethod(obj,MUIM_DoDrag, touch_x, touch_y, 0);
6215 else if (data->icld_LassoActive == TRUE)
6217 #if defined(DEBUG_ILC_EVENTS) || defined(DEBUG_ILC_LASSO)
6218 D(bug("[IconList] %s: Update Lasso\n", __PRETTY_FUNCTION__));
6219 #endif
6220 /* Lasso active */
6221 struct Rectangle new_lasso,
6222 old_lasso;
6223 struct Rectangle iconrect;
6225 struct IconEntry *node = NULL;
6226 // struct IconEntry *new_selected = NULL;
6228 /* Remove previous Lasso frame */
6229 GetAbsoluteLassoRect(data, &old_lasso);
6230 IconList_InvertLassoOutlines(obj, data, &old_lasso);
6232 /* if the mouse leaves our visible area scroll the view */
6233 if (mx < 0 || mx >= _mwidth(obj) || my < 0 || my >= _mheight(obj))
6235 LONG newleft = data->icld_ViewX;
6236 LONG newtop = data->icld_ViewY;
6238 if (mx >= _mwidth(obj)) newleft += (mx - _mwidth(obj));
6239 else if (mx < 0) newleft += mx;
6240 if (my >= _mheight(obj)) newtop += (my - _mheight(obj));
6241 else if (my < 0) newtop += my;
6243 if (newleft + _mwidth(obj) > data->icld_AreaWidth) newleft = data->icld_AreaWidth - _mwidth(obj);
6244 if (newleft < 0) newleft = 0;
6246 if (newtop + _mheight(obj) > data->icld_AreaHeight) newtop = data->icld_AreaHeight - _mheight(obj);
6247 if (newtop < 0) newtop = 0;
6249 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
6251 SetAttrs(obj, MUIA_Virtgroup_Left, newleft, MUIA_Virtgroup_Top, newtop, TAG_DONE);
6255 /* update Lasso coordinates */
6256 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
6257 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
6259 /* get absolute Lasso coordinates */
6260 GetAbsoluteLassoRect(data, &new_lasso);
6262 LONG current = 0, startIndex = 0, endIndex = 0;
6264 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6266 LONG minY = data->icld_LassoRectangle.MinY,
6267 maxY = data->icld_LassoRectangle.MaxY;
6269 if (minY > maxY)
6271 minY ^= maxY;
6272 maxY ^= minY;
6273 minY ^= maxY;
6276 startIndex = ((minY + 1) - data->icld_LVMAttribs->lmva_HeaderHeight) / data->icld_LVMAttribs->lmva_RowHeight;
6277 endIndex = ((maxY - 1) - data->icld_LVMAttribs->lmva_HeaderHeight) / data->icld_LVMAttribs->lmva_RowHeight;
6280 #if defined(__AROS__)
6281 ForeachNode(&data->icld_IconList, node)
6282 #else
6283 Foreach_Node(&data->icld_IconList, node);
6284 #endif
6286 IPTR update_entry = (IPTR)NULL;
6288 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6290 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6292 update_entry = FALSE;
6294 if ((current >= startIndex) && (current <= endIndex))
6296 //Entry is inside our lasso ..
6297 if (!(node->ie_Flags & ICONENTRY_FLAG_LASSO))
6299 /* check if entry was already selected before */
6300 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6302 Remove(&node->ie_SelectionNode);
6303 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6305 else
6307 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6308 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6310 node->ie_Flags |= ICONENTRY_FLAG_LASSO;
6311 update_entry = (IPTR)node;
6314 else if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
6316 //Entry is no longer inside our lasso - revert its selected state
6317 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6319 Remove(&node->ie_SelectionNode);
6320 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6322 else
6324 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6325 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6327 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
6328 update_entry = (IPTR)node;
6331 current++;
6334 else
6336 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6338 iconrect.MinX = node->ie_IconX;
6339 iconrect.MaxX = node->ie_IconX + node->ie_AreaWidth - 1;
6340 iconrect.MinY = node->ie_IconY;
6341 iconrect.MaxY = node->ie_IconY + node->ie_AreaHeight - 1;
6342 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
6343 (node->ie_AreaWidth < data->icld_IconAreaLargestWidth))
6345 iconrect.MinX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
6346 iconrect.MaxX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
6349 if ((((new_lasso.MaxX + data->icld_ViewX) >= iconrect.MinX) && ((new_lasso.MinX + data->icld_ViewX) <= iconrect.MaxX)) &&
6350 (((new_lasso.MaxY + data->icld_ViewY) >= iconrect.MinY) && ((new_lasso.MinY + data->icld_ViewY) <= iconrect.MaxY)))
6352 //Entry is inside our lasso ..
6353 if (!(node->ie_Flags & ICONENTRY_FLAG_LASSO))
6355 /* check if entry was already selected before */
6356 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6358 Remove(&node->ie_SelectionNode);
6359 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6361 else
6363 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6364 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6366 node->ie_Flags |= ICONENTRY_FLAG_LASSO;
6367 update_entry = (IPTR)node;
6370 else if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
6372 //Entry is no longer inside our lasso - revert its selected state
6373 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6375 Remove(&node->ie_SelectionNode);
6376 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6378 else
6380 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6381 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6383 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
6384 update_entry = (IPTR)node;
6388 if (update_entry)
6390 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
6391 data->update_entry = (struct IconEntry *)update_entry;
6392 MUI_Redraw(obj, MADF_DRAWUPDATE);
6395 /* Draw Lasso frame */
6396 IconList_InvertLassoOutlines(obj, data, &new_lasso);
6399 return MUI_EventHandlerRC_Eat;
6401 else if (data->mouse_pressed & MIDDLE_BUTTON)
6403 /* Content is being scrolled */
6404 LONG newleft, newtop;
6406 newleft = data->click_x - mx;
6407 newtop = data->click_y - my;
6409 if (newleft + _mwidth(obj) > data->icld_AreaWidth) newleft = data->icld_AreaWidth - _mwidth(obj);
6410 if (newleft < 0) newleft = 0;
6412 if (newtop + _mheight(obj) > data->icld_AreaHeight) newtop = data->icld_AreaHeight - _mheight(obj);
6413 if (newtop < 0) newtop = 0;
6415 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
6417 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
6418 MUIA_Virtgroup_Top, newtop,
6419 TAG_DONE);
6422 return MUI_EventHandlerRC_Eat;
6424 break;
6426 case IDCMP_MENUVERIFY:
6428 #if defined(DEBUG_ILC_EVENTS)
6429 D(bug("[IconList] %s: IDCMP_MENUVERIFY\n", __PRETTY_FUNCTION__));
6430 #endif
6432 if (data->icld_LassoActive == TRUE)
6434 /* Remove the lasso if the right mouse button is pressed */
6435 NullifyLasso(data, obj);
6437 break;
6441 return 0;
6445 ///MUIM_IconList_NextIcon()
6446 /**************************************************************************
6447 MUIM_IconList_NextIcon
6448 **************************************************************************/
6449 IPTR IconList__MUIM_IconList_NextIcon(struct IClass *CLASS, Object *obj, struct MUIP_IconList_NextIcon *message)
6451 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6452 struct IconEntry *node = NULL;
6453 struct IconList_Entry *ent = NULL;
6454 IPTR node_successor = (IPTR)NULL;
6456 if (message->entry == NULL) return (IPTR)NULL;
6457 ent = *message->entry;
6459 #if defined(DEBUG_ILC_FUNCS)
6460 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6461 #endif
6463 if ((IPTR)ent == (IPTR)MUIV_IconList_NextIcon_Start)
6465 D(bug("[IconList] %s: Finding First Entry ..\n", __PRETTY_FUNCTION__));
6466 if (message->nextflag == MUIV_IconList_NextIcon_Selected)
6468 node = (struct IconEntry *)GetHead(&data->icld_SelectionList);
6469 if (node != NULL)
6471 node = (struct IconEntry *)((IPTR)node - ((IPTR)&node->ie_SelectionNode - (IPTR)node));
6474 else if (message->nextflag == MUIV_IconList_NextIcon_Visible)
6476 node = (struct IconEntry *)GetHead(&data->icld_IconList);
6477 while (node != NULL)
6479 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6480 break;
6482 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6486 else if ((IPTR)ent != (IPTR)MUIV_IconList_NextIcon_End)
6488 node = (struct IconEntry *)((IPTR)ent - ((IPTR)&node->ie_IconListEntry - (IPTR)node));
6489 if (message->nextflag == MUIV_IconList_NextIcon_Selected)
6491 node_successor = (IPTR)GetSucc(&node->ie_SelectionNode);
6492 if (node_successor != (IPTR)NULL)
6493 node = (struct IconEntry *)((IPTR)node_successor - ((IPTR)&node->ie_SelectionNode - (IPTR)node));
6494 else
6496 D(bug("[IconList] %s: GetSucc() == NULL\n", __PRETTY_FUNCTION__));
6497 node = NULL;
6500 else if (message->nextflag == MUIV_IconList_NextIcon_Visible)
6502 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6503 while (node != NULL)
6505 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6506 break;
6508 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6513 if (node == NULL)
6515 D(bug("[IconList] %s: Returning MUIV_IconList_NextIcon_End\n", __PRETTY_FUNCTION__));
6517 *message->entry = (struct IconList_Entry *)MUIV_IconList_NextIcon_End;
6519 else
6521 D(bug("[IconList] %s: Returning entry for '%s'\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
6523 *message->entry = &node->ie_IconListEntry;
6526 return (IPTR)NULL;
6530 ///MUIM_IconList_GetIconPrivate()
6531 /**************************************************************************
6532 MUIM_IconList_GetIconPrivate
6533 **************************************************************************/
6534 IPTR IconList__MUIM_IconList_GetIconPrivate(struct IClass *CLASS, Object *obj, struct MUIP_IconList_GetIconPrivate *message)
6536 // struct IconList_DATA *data = INST_DATA(CLASS, obj);
6537 struct IconEntry *node = NULL;
6539 if (message->entry == NULL) return (IPTR)NULL;
6541 node = (struct IconEntry *)((IPTR)message->entry - ((IPTR)&node->ie_IconListEntry - (IPTR)node));
6543 return (IPTR)node;
6546 ///MUIM_CreateDragImage()
6547 /**************************************************************************
6548 MUIM_CreateDragImage
6549 **************************************************************************/
6550 IPTR IconList__MUIM_CreateDragImage(struct IClass *CLASS, Object *obj, struct MUIP_CreateDragImage *message)
6552 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6553 struct MUI_DragImage *img = NULL;
6554 LONG first_x = -1,
6555 first_y = -1;
6556 BOOL transp = XGET(obj, MUIA_IconList_DragImageTransparent);
6558 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6559 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6560 #endif
6562 if (!(data->icld_SelectionLastClicked))
6563 DoSuperMethodA(CLASS, obj, (Msg)message);
6565 if ((img = (struct MUI_DragImage *)AllocVec(sizeof(struct MUIP_CreateDragImage), MEMF_CLEAR)))
6567 struct Node *node = NULL;
6568 struct IconEntry *entry = NULL;
6570 #if defined(CREATE_FULL_DRAGIMAGE)
6571 #if defined(__AROS__)
6572 ForeachNode(&data->icld_SelectionList, node)
6573 #else
6574 Foreach_Node(&data->icld_SelectionList, node);
6575 #endif
6577 entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
6578 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) && (entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
6580 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) != ICONLIST_DISP_MODELIST)
6582 if ((first_x == -1) || ((first_x != -1) && (entry->ie_IconX < first_x))) first_x = entry->ie_IconX;
6583 if ((first_y == -1) || ((first_y != -1) && (entry->ie_IconY < first_y))) first_y = entry->ie_IconY;
6585 if (data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH)
6587 if ((entry->ie_IconX + entry->ie_AreaWidth) > img->width) img->width = entry->ie_IconX + entry->ie_AreaWidth;
6588 if ((entry->ie_IconY + entry->ie_AreaHeight) > img->height) img->height = entry->ie_IconY + entry->ie_AreaHeight;
6591 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
6593 if ((entry->ie_IconX + data->icld_IconAreaLargestWidth) > img->width) img->width = entry->ie_IconX + data->icld_IconAreaLargestWidth;
6594 if ((entry->ie_IconY + data->icld_IconAreaLargestHeight) > img->height) img->height = entry->ie_IconY + data->icld_IconAreaLargestHeight;
6597 else
6599 img->height += data->icld_LVMAttribs->lmva_RowHeight;
6603 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6605 first_x = 0;
6606 first_y = -message->touchy;
6607 img->width = data->icld_LVMAttribs->lmva_ColumnWidth[data->icld_LVMAttribs->lmva_ColumnPos[INDEX_TYPE]] +
6608 data->icld_LVMAttribs->lmva_ColumnWidth[data->icld_LVMAttribs->lmva_ColumnPos[INDEX_NAME]];
6609 img->height += 2;
6611 else
6613 img->width = (img->width - first_x) + 2;
6614 img->height = (img->height - first_y) + 2;
6616 #else
6617 entry = data->icld_SelectionLastClicked;
6618 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6620 img->width = _mright(obj) - _mleft(obj);
6621 img->height = data->icld_LVMAttribs->lmva_RowHeight;
6622 first_x = 0;
6623 first_y = 0;
6625 else
6627 img->width = entry->ie_IconWidth;
6628 img->height = entry->ie_IconHeight;
6629 first_x = entry->ie_IconX;
6630 first_y = entry->ie_IconY;
6632 #endif
6634 if (transp)
6636 /* Request 32-bit, because the image will have alpha channel */
6637 img->bm = AllocBitMap(img->width, img->height, 32, BMF_CLEAR, NULL);
6639 else
6641 LONG depth = GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH);
6642 img->bm = AllocBitMap(img->width, img->height, depth, BMF_CLEAR, _screen(obj)->RastPort.BitMap);
6645 if (img->bm)
6647 struct RastPort temprp;
6648 InitRastPort(&temprp);
6649 temprp.BitMap = img->bm;
6650 ULONG minY = 0;
6652 #if defined(CREATE_FULL_DRAGIMAGE)
6653 ForeachNode(&data->icld_SelectionList, node)
6655 entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
6656 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) && (entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
6658 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6660 struct Rectangle field_rect;
6661 ULONG selected = entry->ie_Flags & ICONENTRY_FLAG_SELECTED;
6662 entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED; /* Drawing as not selected actually looks better */
6664 field_rect.MinX = 0; field_rect.MaxX = img->width - 1;
6665 field_rect.MinY = minY; field_rect.MaxY = field_rect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
6666 RenderEntryField(obj, data, entry, &field_rect, INDEX_TYPE, TRUE, FALSE, &temprp);
6668 field_rect.MinX = data->icld_LVMAttribs->lmva_ColumnWidth[data->icld_LVMAttribs->lmva_ColumnPos[INDEX_TYPE]] - 1;
6669 field_rect.MaxX = img->width - 1;
6670 field_rect.MinY = minY; field_rect.MaxY = field_rect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
6671 RenderEntryField(obj, data, entry, &field_rect, INDEX_NAME, FALSE, FALSE, &temprp);
6673 minY += data->icld_LVMAttribs->lmva_RowHeight;
6675 entry->ie_Flags |= selected;
6677 else
6679 LONG offsetx , offsety;
6681 IconList_GetIconImageOffsets(data, entry, &offsetx, &offsety);
6683 DrawIconStateA
6685 &temprp, entry->ie_DiskObj, NULL,
6686 (entry->ie_IconX + 1) - first_x + offsetx, (entry->ie_IconY + 1) - first_y + offsety,
6687 IDS_SELECTED,
6688 __iconList_DrawIconStateTags
6693 #else
6694 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6696 SetABPenDrMd(&temprp, _pens(obj)[MPEN_SHINE], 0, JAM1);
6697 RectFill(&temprp, 0, 0, img->width, img->height);
6699 else
6701 DrawIconStateA
6703 &temprp, entry->ie_DiskObj, NULL,
6704 0, 0,
6705 IDS_SELECTED,
6706 __iconList_DrawIconStateTags
6709 #endif
6710 if (transp)
6711 RastPortSetAlpha(&temprp, data->click_x, data->click_y, img->width, img->height, 0xC0, RPALPHAFLAT);
6712 DeinitRastPort(&temprp);
6715 /* Convert view relative coords to drag image relative. This is done because the "object" that is being
6716 * dragged is virtual (its a collection of icons) and the coords passed to DoDrag are not relative to this
6717 * "object"
6719 img->touchx = first_x + message->touchx;
6720 img->touchy = first_y + message->touchy;
6722 if (transp)
6723 img->flags = MUIF_DRAGIMAGE_SOURCEALPHA;
6724 else
6725 img->flags = 0;
6727 return (IPTR)img;
6731 ///MUIM_DeleteDragImage()
6732 /**************************************************************************
6733 MUIM_DeleteDragImage
6734 **************************************************************************/
6735 IPTR IconList__MUIM_DeleteDragImage(struct IClass *CLASS, Object *obj, struct MUIP_DeleteDragImage *message)
6737 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6739 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6740 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6741 #endif
6743 if (!(data->icld_SelectionLastClicked)) return DoSuperMethodA(CLASS,obj,(Msg)message);
6745 if (message->di)
6747 if (message->di->bm)
6748 FreeBitMap(message->di->bm);
6749 FreeVec(message->di);
6751 return (IPTR)NULL;
6755 ///MUIM_DragQuery()
6756 /**************************************************************************
6757 MUIM_DragQuery
6758 **************************************************************************/
6759 IPTR IconList__MUIM_DragQuery(struct IClass *CLASS, Object *obj, struct MUIP_DragQuery *message)
6761 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6762 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6763 #endif
6765 /* TODO: highlight the possible drop target entry .. */
6767 if (message->obj == obj)
6768 return MUIV_DragQuery_Accept;
6769 else
6771 BOOL is_iconlist = FALSE;
6772 struct IClass *msg_cl = OCLASS(message->obj);
6774 while (msg_cl)
6776 if (msg_cl == CLASS)
6778 is_iconlist = TRUE;
6779 break;
6781 msg_cl = msg_cl->cl_Super;
6783 if (is_iconlist)
6784 return MUIV_DragQuery_Accept;
6787 return MUIV_DragQuery_Refuse;
6791 ///MUIM_DragDrop()
6792 /**************************************************************************
6793 MUIM_DragDrop
6794 **************************************************************************/
6795 IPTR IconList__MUIM_DragDrop(struct IClass *CLASS, Object *obj, struct MUIP_DragDrop *message)
6797 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6799 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6800 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6801 #endif
6803 struct IconList_Entry *entry = (IPTR)MUIV_IconList_NextIcon_Start;
6805 if (data->icld_DragDropEvent)
6807 struct IconList_Drop_SourceEntry *clean_node;
6808 #if defined(DEBUG_ILC_ICONDRAGDROP)
6809 D(bug("[IconList] %s: Cleaning existing IconList_Drop_Event @ %p\n", __PRETTY_FUNCTION__, data->icld_DragDropEvent));
6810 #endif
6811 while ((clean_node = (struct IconList_Drop_SourceEntry *)RemTail(&data->icld_DragDropEvent->drop_SourceList)) != NULL)
6813 FreeVec(clean_node->dropse_Node.ln_Name);
6814 FreeMem(clean_node, sizeof(struct IconList_Drop_SourceEntry));
6816 FreeVec(data->icld_DragDropEvent->drop_TargetPath);
6817 FreeMem(data->icld_DragDropEvent, sizeof(struct IconList_Drop_Event));
6818 data->icld_DragDropEvent = NULL;
6821 /* SANITY CHECK: Get first selected entry from SOURCE iconlist */
6822 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
6824 if ((entry) && ((IPTR)entry != MUIV_IconList_NextIcon_End))
6826 /* Ok.. atleast one entry was dropped .. */
6827 char tmp_dirbuff[256];
6828 BPTR tmp_dirlock = (BPTR) NULL;
6830 BOOL iconMove = FALSE;
6831 struct IconEntry *node = NULL;
6832 struct IconEntry *drop_target_node = NULL;
6833 STRPTR directory_path = NULL;
6834 struct IconList_Drop_Event *dragDropEvent = NULL;
6836 GET(obj, MUIA_IconDrawerList_Drawer, &directory_path);
6838 /* Properly expand the name incase it uses devices rather than volumes */
6839 if (directory_path != NULL)
6841 tmp_dirlock = Lock(directory_path, SHARED_LOCK);
6842 if (tmp_dirlock)
6844 if (NameFromLock(tmp_dirlock, tmp_dirbuff, 256) != 0)
6846 directory_path = tmp_dirbuff;
6848 UnLock(tmp_dirlock);
6851 if ((dragDropEvent = AllocMem(sizeof(struct IconList_Drop_Event), MEMF_CLEAR)) == NULL)
6853 #if defined(DEBUG_ILC_ICONDRAGDROP)
6854 D(bug("[IconList] %s: Failed to allocate IconList_Drop_Event Storage!\n", __PRETTY_FUNCTION__));
6855 #endif
6856 goto dragdropdone;
6858 #if defined(DEBUG_ILC_ICONDRAGDROP)
6859 D(bug("[IconList] %s: Allocated IconList_Drop_Event @ %p\n", __PRETTY_FUNCTION__, dragDropEvent));
6860 #endif
6862 NewList(&dragDropEvent->drop_SourceList);
6864 /* go through list and check if dropped on entry */
6865 int rowCount = 0;
6867 #if defined(__AROS__)
6868 ForeachNode(&data->icld_IconList, node)
6869 #else
6870 Foreach_Node(&data->icld_IconList, node);
6871 #endif
6873 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6875 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6877 ULONG rowTop = _mtop(obj) + (rowCount * data->icld_LVMAttribs->lmva_RowHeight);
6878 rowTop += data->icld_LVMAttribs->lmva_HeaderHeight;
6880 if (((message->x > _mleft(obj)) && (message->x < _mright(obj)))
6881 && ((message->y > rowTop) && (message->y < (rowTop + data->icld_LVMAttribs->lmva_RowHeight))))
6883 drop_target_node = node;
6884 break;
6887 rowCount++;
6890 else
6892 struct Rectangle iconbox;
6893 LONG click_x = message->x - _mleft(obj);
6894 LONG click_y = message->y - _mtop(obj);
6895 iconbox.MinX = node->ie_IconX - data->icld_ViewX;
6896 iconbox.MaxX = (node->ie_IconX + node->ie_AreaWidth) - data->icld_ViewX;
6897 iconbox.MinY = node->ie_IconY - data->icld_ViewY;
6898 iconbox.MaxY = (node->ie_IconY + node->ie_AreaHeight)- data->icld_ViewY;
6900 if ((node->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
6901 (click_x >= iconbox.MinX) &&
6902 (click_x < iconbox.MaxX) &&
6903 (click_y >= iconbox.MinY) &&
6904 (click_y < iconbox.MaxY))
6906 drop_target_node = node;
6907 break;
6912 /* Additional filter - if same window and the target entry is selected (==dragged), then it was intended as a move */
6913 if ((message->obj == obj) && (drop_target_node) && (drop_target_node->ie_Flags & ICONENTRY_FLAG_SELECTED))
6914 drop_target_node = NULL;
6916 if ((drop_target_node != NULL) &&
6917 ((drop_target_node->ie_IconListEntry.type == ST_SOFTLINK) ||
6918 (drop_target_node->ie_IconListEntry.type == ST_ROOT) ||
6919 (drop_target_node->ie_IconListEntry.type == ST_USERDIR) ||
6920 (drop_target_node->ie_IconListEntry.type == ST_LINKDIR) ||
6921 (drop_target_node->ie_IconListEntry.type == ST_FILE) ||
6922 (drop_target_node->ie_IconListEntry.type == ST_LINKFILE)))
6924 /* Dropped on some entry */
6925 if ((drop_target_node->ie_IconListEntry.type != ST_ROOT) && (drop_target_node->ie_IconListEntry.type != ST_SOFTLINK))
6927 if (directory_path)
6929 int fulllen = strlen(directory_path) + strlen(drop_target_node->ie_IconListEntry.label) + 2;
6931 if ((dragDropEvent->drop_TargetPath = AllocVec(fulllen, MEMF_CLEAR)) == NULL)
6933 bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__);
6934 goto dragdropdone;
6936 strcpy(dragDropEvent->drop_TargetPath, directory_path);
6937 AddPart(dragDropEvent->drop_TargetPath, drop_target_node->ie_IconListEntry.label, fulllen);
6939 else
6940 goto dragdropdone;
6942 else
6944 if ((dragDropEvent->drop_TargetPath = AllocVec(strlen(drop_target_node->ie_IconListEntry.label) + 1, MEMF_CLEAR)) == NULL)
6946 bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__);
6947 goto dragdropdone;
6949 strcpy(dragDropEvent->drop_TargetPath, drop_target_node->ie_IconListEntry.label);
6952 #if defined(DEBUG_ILC_ICONDRAGDROP)
6953 D(bug("[IconList] %s: Target Entry Full Path = '%s'\n", __PRETTY_FUNCTION__, dragDropEvent->drop_TargetPath));
6954 #endif
6955 /* mark the Entry the selection was dropped on*/
6956 //drop_target_node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6957 //data->icld_UpdateMode = UPDATE_SINGLEENTRY;
6958 //data->update_entry = drop_target_node;
6959 //MUI_Redraw(obj,MADF_DRAWUPDATE);
6961 else
6963 /* Not dropped on entry -> get path of DESTINATION iconlist */
6964 /* Note: directory_path is NULL when dropped on Wanderer's desktop */
6965 if ((message->obj != obj) && directory_path)
6967 #if defined(DEBUG_ILC_ICONDRAGDROP)
6968 D(bug("[IconList] %s: drop entry: Icons dropped in window '%s'\n", __PRETTY_FUNCTION__, directory_path));
6969 #endif
6970 /* copy path */
6971 if ((dragDropEvent->drop_TargetPath = AllocVec(strlen(directory_path) + 1, MEMF_CLEAR)) != NULL)
6973 strcpy(dragDropEvent->drop_TargetPath, directory_path);
6975 else
6977 #if defined(DEBUG_ILC_ICONDRAGDROP)
6978 D(bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__));
6979 #endif
6980 goto dragdropdone;
6983 else if (message->obj == obj)
6985 #if defined(DEBUG_ILC_ICONDRAGDROP)
6986 D(bug("[IconList] %s: drop entry: Entry Move detected ..\n", __PRETTY_FUNCTION__));
6987 #endif
6988 iconMove = TRUE;
6990 /* Adjust entry posiions .. */
6991 #if defined(DEBUG_ILC_ICONDRAGDROP)
6992 D(bug("[IconList] %s: drop entry: message x,y = %d, %d click = %d, %d..\n", __PRETTY_FUNCTION__, message->x, message->y, data->click_x, data->click_y));
6993 #endif
6994 LONG offset_x = message->x - (data->click_x + _mleft(obj));
6995 LONG offset_y = message->y - (data->click_y + _mtop(obj));
6997 entry = (IPTR)MUIV_IconList_NextIcon_Start;
6998 while ((IPTR)entry != MUIV_IconList_NextIcon_End)
7000 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
7002 if ((IPTR)entry != MUIV_IconList_NextIcon_End)
7004 entry->ile_IconEntry->ie_IconX += offset_x;
7005 entry->ile_IconEntry->ie_IconY += offset_y;
7006 /* Remember new position as provided */
7007 DoMethod(obj, MUIM_IconList_PropagateEntryPos, entry->ile_IconEntry);
7009 SET(obj, MUIA_IconList_IconMoved, (IPTR)entry); // Now notify
7011 MUI_Redraw(obj,MADF_DRAWOBJECT);
7012 DoMethod(obj, MUIM_IconList_CoordsSort);
7014 else
7016 #if defined(DEBUG_ILC_ICONDRAGDROP)
7017 D(bug("[IconList] %s: Icons Dropped on Wanderer Desktop (unhandled)!\n", __PRETTY_FUNCTION__));
7018 #endif
7019 iconMove = TRUE;
7024 if (!(iconMove))
7026 int copycount = 0;
7027 /* Create list of entries to copy .. */
7028 entry = (IPTR)MUIV_IconList_NextIcon_Start;
7029 while ((IPTR)entry != MUIV_IconList_NextIcon_End)
7031 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
7033 if ((IPTR)entry != MUIV_IconList_NextIcon_End)
7035 struct IconList_Drop_SourceEntry *sourceEntry = NULL;
7036 sourceEntry = AllocMem(sizeof(struct IconList_Drop_SourceEntry), MEMF_CLEAR);
7037 if ((entry->type != ST_ROOT) && (entry->type != ST_SOFTLINK))
7039 int fulllen = 0;
7040 char *path = NULL;
7042 GET(message->obj, MUIA_IconDrawerList_Drawer, &path);
7043 /* Properly expand the location in case it uses devices rather than volumes */
7044 if (path != NULL)
7046 tmp_dirlock = Lock(path, SHARED_LOCK);
7047 if (tmp_dirlock)
7049 if (NameFromLock(tmp_dirlock, tmp_dirbuff, 256))
7051 path = tmp_dirbuff;
7053 UnLock(tmp_dirlock);
7056 if (strcasecmp(dragDropEvent->drop_TargetPath, path) != 0)
7058 fulllen = strlen(path) + strlen(entry->ile_IconEntry->ie_IconNode.ln_Name) + 2;
7059 sourceEntry->dropse_Node.ln_Name = AllocVec(fulllen, MEMF_CLEAR);
7060 if (sourceEntry->dropse_Node.ln_Name != NULL)
7062 strcpy(sourceEntry->dropse_Node.ln_Name, path);
7063 AddPart(sourceEntry->dropse_Node.ln_Name, entry->label, fulllen);
7065 #if defined(DEBUG_ILC_ICONDRAGDROP)
7066 D(bug("[IconList] %s: Source Entry (Full Path) = '%s'\n", __PRETTY_FUNCTION__, sourceEntry->dropse_Node.ln_Name));
7067 #endif
7071 else
7073 sourceEntry->dropse_Node.ln_Name = AllocVec(strlen(entry->label) + 1, MEMF_CLEAR);
7074 if (sourceEntry->dropse_Node.ln_Name != NULL)
7075 strcpy(sourceEntry->dropse_Node.ln_Name, entry->label);
7076 #if defined(DEBUG_ILC_ICONDRAGDROP)
7077 D(bug("[IconList] %s: Source Entry = '%s'\n", __PRETTY_FUNCTION__, sourceEntry->dropse_Node.ln_Name));
7078 #endif
7081 if ((sourceEntry->dropse_Node.ln_Name != NULL) && (strcasecmp(dragDropEvent->drop_TargetPath, sourceEntry->dropse_Node.ln_Name) != 0))
7083 copycount += 1;
7084 AddTail(&dragDropEvent->drop_SourceList, &sourceEntry->dropse_Node);
7086 else
7088 #if defined(DEBUG_ILC_ICONDRAGDROP)
7089 D(bug("[IconList] %s: Source == Dest, Skipping!\n", __PRETTY_FUNCTION__));
7090 #endif
7091 FreeVec(sourceEntry->dropse_Node.ln_Name);
7092 FreeMem(sourceEntry, sizeof(struct IconList_Drop_SourceEntry));
7096 if (copycount > 0)
7098 dragDropEvent->drop_TargetObj = obj;
7100 #if defined(DEBUG_ILC_ICONDRAGDROP)
7101 D(bug("[IconList] %s: Causing DROP notification..\n", __PRETTY_FUNCTION__));
7102 #endif
7103 SET(obj, MUIA_IconList_IconsDropped, (IPTR)dragDropEvent);
7104 DoMethod(obj, MUIM_IconList_CoordsSort);
7106 else
7108 FreeVec(dragDropEvent->drop_TargetPath);
7109 FreeMem(dragDropEvent, sizeof(struct IconList_Drop_Event));
7113 else
7115 #if defined(DEBUG_ILC_ICONDRAGDROP)
7116 D(bug("[IconList] %s: BUG - DragDrop received with no source icons!\n", __PRETTY_FUNCTION__));
7117 #endif
7118 NNSET(obj, MUIA_IconList_IconsDropped, (IPTR)NULL);
7121 dragdropdone:
7122 return DoSuperMethodA(CLASS, obj, (Msg)message);
7126 ///MUIM_UnselectAll()
7127 /**************************************************************************
7128 MUIM_UnselectAll
7129 **************************************************************************/
7130 IPTR IconList__MUIM_IconList_UnselectAll(struct IClass *CLASS, Object *obj, Msg message)
7132 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7133 struct Node *node = NULL, *next_node = NULL;
7134 BOOL changed = FALSE;
7136 #if defined(DEBUG_ILC_FUNCS)
7137 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7138 #endif
7140 data->icld_SelectionLastClicked = NULL;
7141 data->icld_FocusIcon = NULL;
7142 #if defined(__AROS__)
7143 ForeachNodeSafe(&data->icld_SelectionList, node, next_node)
7144 #else
7145 Foreach_NodeSafe(&data->icld_SelectionList, node, next_node);
7146 #endif
7148 struct IconEntry *entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
7149 BOOL update_entry = FALSE;
7151 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7153 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
7155 Remove(node);
7156 entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
7157 update_entry = TRUE;
7159 if (entry->ie_Flags & ICONENTRY_FLAG_FOCUS)
7161 entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
7162 update_entry = TRUE;
7166 if (update_entry)
7168 changed = TRUE;
7169 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
7170 data->update_entry = entry;
7171 MUI_Redraw(obj, MADF_DRAWUPDATE);
7175 if (changed)
7176 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
7178 return 1;
7182 ///MUIM_SelectAll()
7183 /**************************************************************************
7184 MUIM_SelectAll
7185 **************************************************************************/
7186 IPTR IconList__MUIM_IconList_SelectAll(struct IClass *CLASS, Object *obj, Msg message)
7188 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7189 struct IconEntry *node = NULL;
7190 BOOL changed = FALSE;
7192 #if defined(DEBUG_ILC_FUNCS)
7193 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7194 #endif
7196 node = (struct IconEntry *)GetHead(&data->icld_IconList);
7198 while (node != NULL)
7200 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7202 BOOL update_entry = FALSE;
7204 if (!(node->ie_Flags & ICONENTRY_FLAG_SELECTED))
7206 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
7207 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
7208 update_entry = TRUE;
7210 data->icld_SelectionLastClicked = node;
7212 else if (node->ie_Flags & ICONENTRY_FLAG_FOCUS)
7214 node->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
7215 update_entry = TRUE;
7218 if (update_entry)
7220 changed = TRUE;
7221 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
7222 data->update_entry = node;
7223 MUI_Redraw(obj, MADF_DRAWUPDATE);
7226 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
7229 if ((data->icld_SelectionLastClicked) && (data->icld_SelectionLastClicked != data->icld_FocusIcon))
7231 data->icld_FocusIcon = data->icld_SelectionLastClicked;
7232 if (!(data->icld_FocusIcon->ie_Flags & ICONENTRY_FLAG_FOCUS))
7234 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
7235 data->icld_FocusIcon->ie_Flags |= ICONENTRY_FLAG_FOCUS;
7236 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
7237 data->update_entry = data->icld_FocusIcon;
7238 MUI_Redraw(obj, MADF_DRAWUPDATE);
7242 if (changed)
7243 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
7245 return 1;
7249 ///IconList__MUIM_IconList_CoordsSort()
7250 IPTR IconList__MUIM_IconList_CoordsSort(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Sort *message)
7252 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7254 struct IconEntry *entry = NULL,
7255 *test_icon = NULL;
7257 struct List list_VisibleIcons;
7258 struct List list_HiddenIcons;
7259 // struct List list_UnplacedIcons;
7262 perform a quick sort of the iconlist based on entry coords
7263 this method DOESNT cause any visual output.
7265 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONSORTING)
7266 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7267 #endif
7269 NewList((struct List*)&list_VisibleIcons);
7270 NewList((struct List*)&list_HiddenIcons);
7272 /*move list into our local list struct(s)*/
7273 while ((entry = (struct IconEntry *)RemTail((struct List*)&data->icld_IconList)))
7275 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7277 AddHead((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
7279 else
7280 AddHead((struct List*)&list_HiddenIcons, (struct Node *)&entry->ie_IconNode);
7283 while ((entry = (struct IconEntry *)RemTail((struct List*)&list_VisibleIcons)))
7285 if ((test_icon = (struct IconEntry *)GetTail(&data->icld_IconList)) != NULL)
7287 while (test_icon != NULL)
7289 if (((data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconX > entry->ie_IconX)) ||
7290 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconY > entry->ie_IconY)))
7292 test_icon = (struct IconEntry *)GetPred(&test_icon->ie_IconNode);
7293 continue;
7295 else break;
7298 while (test_icon != NULL)
7300 if (((data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconY > entry->ie_IconY)) ||
7301 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconX > entry->ie_IconX)))
7303 test_icon = (struct IconEntry *)GetPred(&test_icon->ie_IconNode);
7304 continue;
7306 else break;
7308 Insert((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode, (struct Node *)&test_icon->ie_IconNode);
7310 else
7311 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7313 #if defined(DEBUG_ILC_ICONSORTING)
7314 D(bug("[IconList] %s: Done\n", __PRETTY_FUNCTION__));
7315 #endif
7317 while ((entry = (struct IconEntry *)RemTail((struct List*)&list_HiddenIcons)))
7319 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7322 #if defined(DEBUG_ILC_ICONSORTING_DUMP)
7323 #if defined(__AROS__)
7324 ForeachNode(&data->icld_IconList, entry)
7325 #else
7326 Foreach_Node(&data->icld_IconList, entry);
7327 #endif
7329 D(bug("[IconList] %s: %d %d '%s'\n", __PRETTY_FUNCTION__, entry->ie_IconX, entry->ie_IconY, entry->ie_IconListEntry.label));
7331 #endif
7333 return TRUE;
7337 ///MUIM_Sort()
7338 /**************************************************************************
7339 MUIM_Sort - sortsort
7340 **************************************************************************/
7341 IPTR IconList__MUIM_IconList_Sort(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Sort *message)
7343 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7344 struct IconEntry *entry = NULL,
7345 *icon1 = NULL,
7346 *icon2 = NULL;
7348 struct List list_VisibleIcons,
7349 list_SortedIcons,
7350 list_HiddenIcons;
7352 BOOL sortme, reversable = TRUE, enqueue = FALSE;
7353 int i, visible_count = 0;
7355 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONSORTING)
7356 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7357 #endif
7359 /* Reset incase view options have changed .. */
7360 data->icld_IconAreaLargestWidth = 0;
7361 data->icld_IconAreaLargestHeight = 0;
7362 data->icld_IconLargestHeight = 0;
7363 data->icld_LabelLargestHeight = 0;
7365 #if defined(DEBUG_ILC_ICONSORTING)
7366 D(bug("[IconList] %s: Sort-Flags : %x\n", __PRETTY_FUNCTION__, (data->icld_SortFlags & MUIV_IconList_Sort_MASK)));
7367 #endif
7368 NewList((struct List*)&list_VisibleIcons);
7369 NewList((struct List*)&list_SortedIcons);
7370 NewList((struct List*)&list_HiddenIcons);
7372 /*move list into our local list struct(s)*/
7373 while ((entry = (struct IconEntry *)RemTail((struct List*)&data->icld_IconList)))
7375 if (!(entry->ie_Flags & ICONENTRY_FLAG_HASICON))
7377 if (data->icld_DisplayFlags & ICONLIST_DISP_SHOWINFO)
7379 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7381 entry->ie_Flags &= ~(ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
7384 else if (!(entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
7386 entry->ie_Flags |= (ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
7389 else
7391 if (!(entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
7393 entry->ie_Flags |= (ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
7397 /* Now we have fixed visibility lets dump them into the correct list for sorting */
7398 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7400 if(entry->ie_AreaWidth > data->icld_IconAreaLargestWidth) data->icld_IconAreaLargestWidth = entry->ie_AreaWidth;
7401 if(entry->ie_AreaHeight > data->icld_IconAreaLargestHeight) data->icld_IconAreaLargestHeight = entry->ie_AreaHeight;
7402 if(entry->ie_IconHeight > data->icld_IconLargestHeight) data->icld_IconLargestHeight = entry->ie_IconHeight;
7403 if((entry->ie_AreaHeight - entry->ie_IconHeight) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = entry->ie_AreaHeight - entry->ie_IconHeight;
7405 if (((data->icld_SortFlags & MUIV_IconList_Sort_AutoSort) == 0) && (entry->ie_ProvidedIconX == NO_ICON_POSITION))
7406 AddTail((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
7407 else
7408 AddHead((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
7409 visible_count++;
7411 else
7413 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
7415 Remove(&entry->ie_SelectionNode);
7417 entry->ie_Flags &= ~(ICONENTRY_FLAG_SELECTED|ICONENTRY_FLAG_FOCUS);
7418 if (data->icld_SelectionLastClicked == entry) data->icld_SelectionLastClicked = NULL;
7419 if (data->icld_FocusIcon == entry) data->icld_FocusIcon = data->icld_SelectionLastClicked;
7420 AddHead((struct List*)&list_HiddenIcons, (struct Node *)&entry->ie_IconNode);
7424 /* Copy each visible entry back to the main list, sorting as we go*/
7425 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_VisibleIcons)))
7427 icon1 = (struct IconEntry *)GetHead(&list_SortedIcons);
7428 icon2 = NULL;
7430 sortme = FALSE;
7432 if (visible_count > 1)
7434 #if defined(DEBUG_ILC_ICONSORTING)
7435 D(bug("[IconList] %s: - %s %s %s %i\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label, entry->ie_TxtBuf_DATE, entry->ie_TxtBuf_TIME, entry->ie_FileInfoBlock->fib_Size));
7436 #endif
7437 while (icon1)
7439 if(((icon1->ie_IconListEntry.type == ST_ROOT) || (icon1->ie_IconListEntry.type == ST_LINKDIR) || (icon1->ie_IconListEntry.type == ST_LINKFILE))
7440 || (data->icld_SortFlags & MUIV_IconList_Sort_DrawersMixed))
7442 /*volume list or drawers mixed*/
7443 sortme = TRUE;
7445 else
7447 /*drawers first*/
7448 if ((icon1->ie_IconListEntry.type == ST_USERDIR) && (entry->ie_IconListEntry.type == ST_USERDIR))
7450 sortme = TRUE;
7452 else
7454 if ((icon1->ie_IconListEntry.type != ST_USERDIR) && (entry->ie_IconListEntry.type != ST_USERDIR))
7455 sortme = TRUE;
7456 else
7458 /* we are the first drawer to arrive or we need to insert ourselves
7459 due to being sorted to the end of the drawers*/
7461 if ((!icon2 || icon2->ie_IconListEntry.type == ST_USERDIR) &&
7462 (entry->ie_IconListEntry.type == ST_USERDIR) &&
7463 (icon1->ie_IconListEntry.type != ST_USERDIR))
7465 #if defined(DEBUG_ILC_ICONSORTING)
7466 D(bug("[IconList] %s: force %s\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label));
7467 #endif
7468 break;
7474 if (sortme)
7476 i = 0;
7478 if ((data->icld_SortFlags & MUIV_IconList_Sort_AutoSort) == 0)
7480 if ((entry->ie_ProvidedIconX != NO_ICON_POSITION) && (entry->ie_ProvidedIconY != NO_ICON_POSITION))
7482 i = 1;
7486 if (i == 0)
7488 if (data->icld_SortFlags & MUIV_IconList_Sort_ByDate)
7490 /* Sort by Date */
7491 i = CompareDates((const struct DateStamp *)&entry->ie_FileInfoBlock->fib_Date,(const struct DateStamp *)&icon1->ie_FileInfoBlock->fib_Date);
7493 else if (data->icld_SortFlags & MUIV_IconList_Sort_BySize)
7495 /* Sort by Size .. */
7496 i = entry->ie_FileInfoBlock->fib_Size - icon1->ie_FileInfoBlock->fib_Size;
7498 else if ((data->icld_SortFlags & MUIV_IconList_Sort_ByType) && ((entry->ie_IconListEntry.type == ST_FILE) || (entry->ie_IconListEntry.type == ST_USERDIR)))
7500 /* Sort by Type .. */
7501 /* TODO: Sort icons based on type using datatypes */
7503 else
7505 /* Sort by Name .. */
7506 i = Stricmp(entry->ie_IconListEntry.label, icon1->ie_IconListEntry.label);
7507 if ((data->icld_SortFlags & MUIV_IconList_Sort_DrawersMixed) == 0) enqueue = TRUE;
7511 if ((reversable) && data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
7513 if (i > 0)
7514 break;
7516 else if (i < 0)
7517 break;
7519 icon2 = icon1;
7520 icon1 = (struct IconEntry *)GetSucc(&icon1->ie_IconNode);
7523 Insert((struct List*)&list_SortedIcons, (struct Node *)&entry->ie_IconNode, (struct Node *)&icon2->ie_IconNode);
7525 if (enqueue)
7527 /* Quickly resort based on node priorities .. */
7528 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_SortedIcons)))
7530 Enqueue((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7533 else
7535 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_SortedIcons)))
7537 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7541 DoMethod(obj, MUIM_IconList_PositionIcons);
7542 MUI_Redraw(obj, MADF_DRAWOBJECT);
7544 if ((data->icld_SortFlags & MUIV_IconList_Sort_Orders) != 0)
7546 DoMethod(obj, MUIM_IconList_CoordsSort);
7548 /* leave hidden icons on a seperate list to speed up normal list parsing ? */
7549 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_HiddenIcons)))
7551 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7554 SET(obj, MUIA_IconList_Changed, TRUE);
7556 return 1;
7560 ///MUIM_DragReport()
7561 /**************************************************************************
7562 MUIM_DragReport. Since MUI doesn't change the drop object if the dragged
7563 object is moved above another window (while still in the bounds of the
7564 orginal drop object) we must do it here manually to be compatible with
7565 MUI. Maybe Zune should fix this bug somewhen.
7566 **************************************************************************/
7567 IPTR IconList__MUIM_DragReport(struct IClass *CLASS, Object *obj, struct MUIP_DragReport *message)
7569 struct Window *wnd = _window(obj);
7570 struct Layer *l = NULL;
7572 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
7573 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7574 #endif
7576 LockLayerInfo(&wnd->WScreen->LayerInfo);
7577 l = WhichLayer(&wnd->WScreen->LayerInfo, wnd->LeftEdge + message->x, wnd->TopEdge + message->y);
7578 UnlockLayerInfo(&wnd->WScreen->LayerInfo);
7580 if (l != wnd->WLayer) return MUIV_DragReport_Abort;
7582 return MUIV_DragReport_Continue;
7586 ///MUIM_IconList_UnknownDropDestination()
7587 /**************************************************************************
7588 MUIM_IconList_UnknownDropDestination
7589 **************************************************************************/
7590 IPTR IconList__MUIM_UnknownDropDestination(struct IClass *CLASS, Object *obj, struct MUIP_UnknownDropDestination *message)
7592 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
7593 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7594 #endif
7595 #if defined(DEBUG_ILC_ICONDRAGDROP)
7596 D(bug("[IconList] %s: icons dropped on custom window \n", __PRETTY_FUNCTION__));
7597 #endif
7599 SET(obj, MUIA_IconList_AppWindowDrop, (IPTR)message); /* Now notify */
7601 return (IPTR)NULL;
7605 ///MUIM_IconList_MakeEntryVisible()
7606 /**************************************************************************
7607 Move the visible area so that the selected entry becomes visible ..
7608 **************************************************************************/
7609 IPTR IconList__MUIM_IconList_MakeEntryVisible(struct IClass *CLASS, Object *obj, struct MUIP_IconList_MakeEntryVisible *message)
7611 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7612 BOOL viewmoved = FALSE;
7613 struct Rectangle iconrect, viewrect;
7615 #if defined(DEBUG_ILC_FUNCS)
7616 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7617 #endif
7619 viewrect.MinX = data->icld_ViewX;
7620 viewrect.MaxX = data->icld_ViewX + data->icld_AreaWidth;
7621 viewrect.MinY = data->icld_ViewY;
7622 viewrect.MaxY = data->icld_ViewY + data->icld_AreaHeight;
7624 IconList_GetIconAreaRectangle(obj, data, message->entry, &iconrect);
7626 if (!(RectAndRect(&viewrect, &iconrect)))
7628 viewmoved = TRUE;
7629 if (message->entry->ie_IconX < data->icld_ViewX)
7630 data->icld_ViewX = message->entry->ie_IconX;
7631 else if (message->entry->ie_IconX > (data->icld_ViewX + data->icld_AreaWidth))
7632 data->icld_ViewX = (message->entry->ie_IconX + message->entry->ie_AreaWidth) - data->icld_AreaWidth;
7634 if (message->entry->ie_IconY < data->icld_ViewY)
7635 data->icld_ViewY = message->entry->ie_IconX;
7636 else if (message->entry->ie_IconY > (data->icld_ViewY + data->icld_AreaHeight))
7637 data->icld_ViewY = (message->entry->ie_IconY + message->entry->ie_AreaHeight) - data->icld_AreaHeight;
7640 if (viewmoved)
7642 #if defined(DEBUG_ILC_ICONRENDERING)
7643 D(bug("[IconList]: %s: call SetSuperAttrs()\n", __PRETTY_FUNCTION__));
7644 #endif
7645 SetSuperAttrs(CLASS, obj, MUIA_Virtgroup_Left, data->icld_ViewX,
7646 MUIA_Virtgroup_Top, data->icld_ViewY,
7647 TAG_DONE);
7649 #if defined(DEBUG_ILC_ICONRENDERING)
7650 D(bug("[IconList]: %s: call SetAttrs()\n", __PRETTY_FUNCTION__));
7651 #endif
7652 SetAttrs(obj, MUIA_Virtgroup_Left, data->icld_ViewX,
7653 MUIA_Virtgroup_Top, data->icld_ViewY,
7654 TAG_DONE);
7656 #if defined(DEBUG_ILC_ICONRENDERING)
7657 D(bug("[IconList]: %s: call MUI_Redraw()\n", __PRETTY_FUNCTION__));
7658 #endif
7659 MUI_Redraw(obj,MADF_DRAWOBJECT);
7661 return 1;
7664 #if defined(WANDERER_BUILTIN_ICONLIST)
7665 BOOPSI_DISPATCHER(IPTR,IconList_Dispatcher, CLASS, obj, message)
7667 #if defined(__AROS__)
7668 switch (message->MethodID)
7669 #else
7670 struct IClass *CLASS = cl;
7671 Msg message = msg;
7673 switch (msg->MethodID)
7674 #endif
7676 case OM_NEW: return IconList__OM_NEW(CLASS, obj, (struct opSet *)message);
7677 case OM_DISPOSE: return IconList__OM_DISPOSE(CLASS, obj, message);
7678 case OM_SET: return IconList__OM_SET(CLASS, obj, (struct opSet *)message);
7679 case OM_GET: return IconList__OM_GET(CLASS, obj, (struct opGet *)message);
7680 case OM_ADDMEMBER:
7681 case MUIM_Family_AddTail: return IconList__MUIM_Family_AddTail(CLASS, obj, (APTR)message);
7682 case MUIM_Family_AddHead: return IconList__MUIM_Family_AddHead(CLASS, obj, (APTR)message);
7683 case OM_REMMEMBER:
7684 case MUIM_Family_Remove: return IconList__MUIM_Family_Remove(CLASS, obj, (APTR)message);
7686 case MUIM_Setup: return IconList__MUIM_Setup(CLASS, obj, (struct MUIP_Setup *)message);
7688 case MUIM_Show: return IconList__MUIM_Show(CLASS,obj, (struct MUIP_Show *)message);
7689 case MUIM_Hide: return IconList__MUIM_Hide(CLASS,obj, (struct MUIP_Hide *)message);
7690 case MUIM_Cleanup: return IconList__MUIM_Cleanup(CLASS, obj, (struct MUIP_Cleanup *)message);
7691 case MUIM_AskMinMax: return IconList__MUIM_AskMinMax(CLASS, obj, (struct MUIP_AskMinMax *)message);
7692 case MUIM_Draw: return IconList__MUIM_Draw(CLASS, obj, (struct MUIP_Draw *)message);
7693 #if defined(__AROS__)
7694 case MUIM_Layout: return IconList__MUIM_Layout(CLASS, obj, (struct MUIP_Layout *)message);
7695 #endif
7696 case MUIM_HandleEvent: return IconList__MUIM_HandleEvent(CLASS, obj, (struct MUIP_HandleEvent *)message);
7697 case MUIM_CreateDragImage: return IconList__MUIM_CreateDragImage(CLASS, obj, (APTR)message);
7698 case MUIM_DeleteDragImage: return IconList__MUIM_DeleteDragImage(CLASS, obj, (APTR)message);
7699 case MUIM_DragQuery: return IconList__MUIM_DragQuery(CLASS, obj, (APTR)message);
7700 case MUIM_DragReport: return IconList__MUIM_DragReport(CLASS, obj, (APTR)message);
7701 case MUIM_DragDrop: return IconList__MUIM_DragDrop(CLASS, obj, (APTR)message);
7702 #if defined(__AROS__)
7703 case MUIM_UnknownDropDestination: return IconList__MUIM_UnknownDropDestination(CLASS, obj, (APTR)message);
7704 #endif
7705 case MUIM_IconList_Update: return IconList__MUIM_IconList_Update(CLASS, obj, (APTR)message);
7706 case MUIM_IconList_Clear: return IconList__MUIM_IconList_Clear(CLASS, obj, (APTR)message);
7707 case MUIM_IconList_RethinkDimensions: return IconList__MUIM_IconList_RethinkDimensions(CLASS, obj, (APTR)message);
7708 case MUIM_IconList_CreateEntry: return IconList__MUIM_IconList_CreateEntry(CLASS, obj, (APTR)message);
7709 case MUIM_IconList_UpdateEntry: return IconList__MUIM_IconList_UpdateEntry(CLASS, obj, (APTR)message);
7710 case MUIM_IconList_DestroyEntry: return IconList__MUIM_IconList_DestroyEntry(CLASS, obj, (APTR)message);
7711 case MUIM_IconList_DrawEntry: return IconList__MUIM_IconList_DrawEntry(CLASS, obj, (APTR)message);
7712 case MUIM_IconList_DrawEntryLabel: return IconList__MUIM_IconList_DrawEntryLabel(CLASS, obj, (APTR)message);
7713 case MUIM_IconList_NextIcon: return IconList__MUIM_IconList_NextIcon(CLASS, obj, (APTR)message);
7714 case MUIM_IconList_GetIconPrivate: return IconList__MUIM_IconList_GetIconPrivate(CLASS, obj, (APTR)message);
7715 case MUIM_IconList_UnselectAll: return IconList__MUIM_IconList_UnselectAll(CLASS, obj, (APTR)message);
7716 case MUIM_IconList_Sort: return IconList__MUIM_IconList_Sort(CLASS, obj, (APTR)message);
7717 case MUIM_IconList_CoordsSort: return IconList__MUIM_IconList_CoordsSort(CLASS, obj, (APTR)message);
7718 case MUIM_IconList_PositionIcons: return IconList__MUIM_IconList_PositionIcons(CLASS, obj, (APTR)message);
7719 case MUIM_IconList_SelectAll: return IconList__MUIM_IconList_SelectAll(CLASS, obj, (APTR)message);
7720 case MUIM_IconList_MakeEntryVisible: return IconList__MUIM_IconList_MakeEntryVisible(CLASS, obj, (APTR)message);
7723 return DoSuperMethodA(CLASS, obj, message);
7725 BOOPSI_DISPATCHER_END
7727 #if defined(__AROS__)
7728 /* Class descriptor. */
7729 const struct __MUIBuiltinClass _MUI_IconList_desc = {
7730 MUIC_IconList,
7731 MUIC_Area,
7732 sizeof(struct IconList_DATA),
7733 (void*)IconList_Dispatcher
7735 #endif
7736 #endif /* WANDERER_BUILTIN_ICONLIST */
7738 #if !defined(__AROS__)
7739 struct MUI_CustomClass *initIconListClass(void)
7741 return (struct MUI_CustomClass *) MUI_CreateCustomClass(NULL, MUIC_Area, NULL, sizeof(struct IconList_DATA), ENTRY(IconList_Dispatcher));
7743 #endif