grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / system / Wanderer / Classes / iconlist.c
blobcedcf7de9b336076932afa30f7ff456ca047909d
1 /*
2 Copyright © 2001-2013, 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, 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 static void RenderEntryField(Object *obj, struct IconList_DATA *data,
739 struct IconEntry *entry, struct Rectangle *rect, LONG index, BOOL firstvis,
740 BOOL lastvis, struct RastPort * rp)
742 STRPTR text = NULL, renderflag = "<UHOH>";
743 struct TextExtent te;
744 ULONG fit;
746 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
748 FillPixelArray(rp,
749 rect->MinX, rect->MinY,
750 rect->MaxX - rect->MinX + 1, rect->MaxY - rect->MinY,
751 0x0A246A);
754 rect->MinX += ENTRY_SPACING_LEFT;
755 rect->MaxX -= ENTRY_SPACING_RIGHT;
756 rect->MinY += LINE_SPACING_TOP;
757 rect->MaxY -= LINE_SPACING_BOTTOM;
759 if (firstvis) rect->MinX += LINE_SPACING_LEFT;
760 if (lastvis) rect->MaxX -= LINE_SPACING_RIGHT;
762 if (!entry) return;
764 switch(index)
766 case INDEX_TYPE:
767 /* Special case !! we draw an image instead .. */
768 text = renderflag;
769 break;
771 case INDEX_NAME:
772 text = entry->ie_IconListEntry.label;
773 break;
775 case INDEX_SIZE:
776 text = entry->ie_TxtBuf_SIZE;
777 break;
779 case INDEX_LASTACCESS:
780 text = AllocVec(strlen(entry->ie_TxtBuf_DATE) + strlen(entry->ie_TxtBuf_TIME) + 5, MEMF_CLEAR);
781 if (text)
782 sprintf(text, "%s at %s", entry->ie_TxtBuf_DATE,
783 entry->ie_TxtBuf_TIME);
784 break;
786 case INDEX_COMMENT:
787 text = entry->ie_FileInfoBlock->fib_Comment;
788 break;
790 case INDEX_PROTECTION:
791 text = entry->ie_TxtBuf_PROT;
792 break;
795 if (!text) return;
796 if (!text[0]) return;
798 if (text == renderflag)
800 if (entry->ie_IconListEntry.type == ST_USERDIR)
802 if (data->icld_LVMAttribs->lvma_IconDrawer)
804 DrawIconStateA
806 rp, data->icld_LVMAttribs->lvma_IconDrawer, NULL,
807 rect->MinX + 1, rect->MinY + 1,
808 (entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
809 __iconList_DrawIconStateTags
812 else
814 FillPixelArray(rp,
815 rect->MinX + 1, rect->MinY + 1,
816 rect->MaxX - rect->MinX - 1, rect->MaxY - rect->MinY - 1,
817 0xc0f0f0);
820 else
822 if (data->icld_LVMAttribs->lvma_IconFile)
824 DrawIconStateA
826 rp, data->icld_LVMAttribs->lvma_IconFile, NULL,
827 rect->MinX + 1, rect->MinY + 1,
828 (entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
829 __iconList_DrawIconStateTags
832 else
834 FillPixelArray(rp,
835 rect->MinX + 1, rect->MinY + 1,
836 rect->MaxX - rect->MinX - 1, rect->MaxY - rect->MinY - 1,
837 0xe0e0e0);
841 else
843 fit = TextFit(rp, text, strlen(text), &te, NULL, 1,
844 rect->MaxX - rect->MinX + 1,
845 rect->MaxY - rect->MinY + 1);
847 if (!fit) return;
849 SetABPenDrMd(rp, _pens(obj)[(entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? MPEN_SHINE : MPEN_TEXT], 0, JAM1);
851 if (((rect->MaxY - rect->MinY + 1) - data->icld_IconLabelFont->tf_YSize) > 0)
853 rect->MinY += ((rect->MaxY - rect->MinY + 1) - data->icld_IconLabelFont->tf_YSize)/2;
856 switch(data->icld_LVMAttribs->lmva_ColumnHAlign[index])
858 case COLUMN_ALIGN_LEFT:
859 Move(rp, rect->MinX, rect->MinY + rp->TxBaseline);
860 break;
862 case COLUMN_ALIGN_RIGHT:
863 Move(rp, rect->MaxX - te.te_Width, rect->MinY + rp->TxBaseline);
864 break;
866 case COLUMN_ALIGN_CENTER:
867 Move(rp, rect->MinX + (rect->MaxX - rect->MinX + 1 + 1 - te.te_Width) / 2,
868 rect->MinY + rp->TxBaseline);
869 break;
872 Text(rp, text, fit);
874 if ((index == INDEX_LASTACCESS) && text)
875 FreeVec(text);
879 /**************************************************************************
880 Draw the entry at its position
881 **************************************************************************/
882 ///IconList__MUIM_IconList_DrawEntry()
883 IPTR IconList__MUIM_IconList_DrawEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DrawEntry *message)
885 struct IconList_DATA *data = INST_DATA(CLASS, obj);
887 BOOL outside = FALSE;
889 struct Rectangle iconrect;
890 struct Rectangle objrect;
892 ULONG objX, objY, objW, objH;
893 LONG iconX, iconY;
895 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
897 objX = _mleft(obj);
898 objY = _mtop(obj);
900 else
902 objX = objY = 0;
904 objW = _mright(obj) - _mleft(obj) + 1;
905 objH = _mbottom(obj) - _mtop(obj) + 1;
907 #if defined(DEBUG_ILC_ICONRENDERING)
908 D(bug("[IconList]: %s(message->entry = 0x%p)\n", __PRETTY_FUNCTION__, message->entry));
909 #endif
911 if ((!(message->entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)) ||
912 (data->icld_BufferRastPort == NULL) ||
913 (!(message->entry->ie_DiskObj)))
915 #if defined(DEBUG_ILC_ICONRENDERING)
916 D(bug("[IconList] %s: Not visible or missing DOB\n", __PRETTY_FUNCTION__));
917 #endif
918 return FALSE;
921 /* Set the dimensions of our "view" */
922 objrect.MinX = objX;
923 objrect.MinY = objY;
924 objrect.MaxX = objX + objW - 1;
925 objrect.MaxY = objY + objH - 1;
927 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
929 struct Rectangle linerect;
930 LONG x, i;
931 LONG firstvis, lastvis;
933 linerect.MinX = objX - data->icld_ViewX;
934 linerect.MaxX = objX + objW - 1; //linerect.MinX + data->width - 1;
935 linerect.MinY = (objY - data->icld_ViewY) + data->icld_LVMAttribs->lmva_HeaderHeight + (message->drawmode * data->icld_LVMAttribs->lmva_RowHeight);
936 linerect.MaxY = linerect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
938 if (!AndRectRect(&linerect, &objrect, NULL)) return FALSE;
939 // if (!MustRenderRect(data, &linerect)) return;
941 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
943 x = linerect.MinX + LINE_SPACING_LEFT;
945 firstvis = FirstVisibleColumnNumber(data);
946 lastvis = LastVisibleColumnNumber(data);
948 for(i = 0; i < NUM_COLUMNS; i++)
950 struct Rectangle field_rect;
951 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
953 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[i] & LVMCF_COLVISIBLE)) continue;
955 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
956 field_rect.MinY = linerect.MinY;
957 field_rect.MaxX = x + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1 + ((i == lastvis) ? LINE_SPACING_RIGHT : 0);
958 field_rect.MaxY = linerect.MaxY;
960 /* if (MustRenderRect(data, &field_rect))
962 if (AndRectRect(&field_rect, &objrect, NULL))
964 RenderEntryField(obj, data, message->entry, &field_rect, index,
965 (i == firstvis), (i == lastvis), data->icld_BufferRastPort);
967 /* }*/
968 x += data->icld_LVMAttribs->lmva_ColumnWidth[index];
971 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_ROWDRAWTOEND) == LVMAF_ROWDRAWTOEND)
973 x += LINE_SPACING_RIGHT;
975 if (x < linerect.MaxX)
977 linerect.MinX = x;
979 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_SHINE], 0, JAM1);
980 RectFill(data->icld_BufferRastPort, linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
984 else
986 LONG offsetx,offsety;
988 /* Get the dimensions and affected area of message->entry */
989 IconList_GetIconImageRectangle(obj, data, message->entry, &iconrect);
991 /* Get offset corrections */
992 IconList_GetIconImageOffsets(data, message->entry, &offsetx, &offsety);
994 /* Add the relative position offset of the message->entry */
995 iconrect.MinX += objX - data->icld_ViewX + message->entry->ie_IconX + offsetx;
996 iconrect.MaxX += objX - data->icld_ViewX + message->entry->ie_IconX + offsetx;
997 iconrect.MinY += objY - data->icld_ViewY + message->entry->ie_IconY + offsety;
998 iconrect.MaxY += objY - data->icld_ViewY + message->entry->ie_IconY + offsety;
1000 if (!RectAndRect(&iconrect, &objrect))
1002 #if defined(DEBUG_ILC_ICONRENDERING)
1003 D(bug("[IconList] %s: Entry '%s' image outside of visible area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1004 #endif
1005 return FALSE;
1008 /* data->update_rect1 and data->update_rect2 may
1009 point to rectangles to indicate that only icons
1010 in any of this rectangles need to be drawn */
1011 if (data->update_rect1)
1013 if (!RectAndRect(&iconrect, data->update_rect1)) outside = TRUE;
1016 if (data->update_rect2)
1018 if (data->update_rect1)
1020 if ((outside == TRUE) && RectAndRect(&iconrect, data->update_rect2))
1021 outside = FALSE;
1023 else
1025 if (!RectAndRect(&iconrect, data->update_rect2))
1026 outside = TRUE;
1030 if (outside == TRUE)
1032 #if defined(DEBUG_ILC_ICONRENDERING)
1033 D(bug("[IconList] %s: Entry '%s' image outside of update area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1034 #endif
1035 return FALSE;
1038 if (message->drawmode == ICONENTRY_DRAWMODE_NONE) return TRUE;
1040 // Center entry image
1041 iconX = iconrect.MinX - objX + data->icld_DrawOffsetX;
1042 iconY = iconrect.MinY - objY + data->icld_DrawOffsetY;
1044 #if defined(DEBUG_ILC_ICONRENDERING)
1045 D(bug("[IconList] %s: DrawIconState('%s') .. %d, %d\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label, iconX, iconY));
1046 #endif
1047 DrawIconStateA
1049 data->icld_BufferRastPort, message->entry->ie_DiskObj, NULL,
1050 iconX,
1051 iconY,
1052 (message->entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
1053 __iconList_DrawIconStateTags
1055 #if defined(DEBUG_ILC_ICONRENDERING)
1056 D(bug("[IconList] %s: DrawIconState Done\n", __PRETTY_FUNCTION__));
1057 #endif
1060 return TRUE;
1064 ///IconList__LabelFunc_SplitLabel()
1065 static void IconList__LabelFunc_SplitLabel(Object *obj, struct IconList_DATA *data, struct IconEntry *entry)
1067 ULONG labelSplit_MaxLabelLineLength = data->icld__Option_LabelTextMaxLen;
1068 ULONG labelSplit_LabelLength = strlen(entry->ie_IconListEntry.label);
1069 ULONG txwidth;
1070 // ULONG labelSplit_FontY = data->icld_IconLabelFont->tf_YSize;
1071 int labelSplit_CharsDone, labelSplit_CharsSplit;
1072 ULONG labelSplit_CurSplitWidth;
1074 if ((data->icld__Option_TrimVolumeNames) &&
1075 ((entry->ie_IconListEntry.type == ST_ROOT) && (entry->ie_IconListEntry.label[labelSplit_LabelLength - 1] == ':')))
1076 labelSplit_LabelLength--;
1078 if (labelSplit_MaxLabelLineLength >= labelSplit_LabelLength)
1080 #if defined(DEBUG_ILC_ICONRENDERING)
1081 D(bug("[IconList]: %s: Label'%s' doesnt need split (onyl %d chars)\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label, labelSplit_LabelLength));
1082 #endif
1083 return;
1086 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
1087 txwidth = TextLength(data->icld_BufferRastPort, entry->ie_IconListEntry.label, labelSplit_MaxLabelLineLength);
1088 #if defined(DEBUG_ILC_ICONRENDERING)
1089 D(bug("[IconList]: %s: txwidth = %d\n", __PRETTY_FUNCTION__, txwidth));
1090 #endif
1091 entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, 256);
1092 if (entry->ie_TxtBuf_DisplayedLabel != NULL)
1093 memset(entry->ie_TxtBuf_DisplayedLabel, 0, 256);
1094 entry->ie_SplitParts = 0;
1096 labelSplit_CharsDone = 0;
1097 labelSplit_CharsSplit = 0;
1098 labelSplit_CurSplitWidth = 0;
1100 while (labelSplit_CharsDone < labelSplit_LabelLength)
1102 ULONG labelSplit_CurSplitLength = labelSplit_LabelLength - labelSplit_CharsDone;
1103 IPTR labelSplit_SplitStart = (IPTR)(entry->ie_IconListEntry.label + labelSplit_CharsDone);
1104 int tmp_checkoffs = 0;
1105 IPTR labelSplit_RemainingCharsAfterSplit;
1106 IPTR labelSplit_CurSplitDest;
1108 while (*(char *)(labelSplit_SplitStart) == ' ')
1110 //Skip preceding spaces..
1111 labelSplit_SplitStart = labelSplit_SplitStart + 1;
1112 labelSplit_CurSplitLength = labelSplit_CurSplitLength - 1;
1113 labelSplit_CharsDone = labelSplit_CharsDone + 1;
1116 while(TextLength(data->icld_BufferRastPort, (char *)labelSplit_SplitStart, labelSplit_CurSplitLength) < txwidth) labelSplit_CurSplitLength++;
1117 while(TextLength(data->icld_BufferRastPort, (char *)labelSplit_SplitStart, labelSplit_CurSplitLength) > txwidth) labelSplit_CurSplitLength--;
1118 #if defined(DEBUG_ILC_ICONRENDERING)
1119 D(bug("[IconList]: %s: labelSplit_CurSplitLength = %d\n", __PRETTY_FUNCTION__, labelSplit_CurSplitLength));
1120 #endif
1122 #if defined(DEBUG_ILC_ICONRENDERING)
1123 D(bug("[IconList]: %s: Attempting to find neat split ", __PRETTY_FUNCTION__));
1124 #endif
1125 while(tmp_checkoffs < (labelSplit_CurSplitLength - ILC_ICONLABEL_SHORTEST))
1127 #if defined(DEBUG_ILC_ICONRENDERING)
1128 D(bug("%d", tmp_checkoffs));
1129 #endif
1130 labelSplit_RemainingCharsAfterSplit = labelSplit_LabelLength - (labelSplit_CharsDone + labelSplit_CurSplitLength);
1132 if ((labelSplit_CurSplitLength - tmp_checkoffs) > ILC_ICONLABEL_SHORTEST)
1134 #if defined(DEBUG_ILC_ICONRENDERING)
1135 D(bug("<"));
1136 #endif
1137 if ((*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == ' ') ||
1138 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == '.') ||
1139 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == '-'))
1141 #if defined(DEBUG_ILC_ICONRENDERING)
1142 D(bug("!"));
1143 #endif
1144 labelSplit_CurSplitLength = labelSplit_CurSplitLength - tmp_checkoffs;
1145 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit - tmp_checkoffs;
1146 tmp_checkoffs = 0;
1147 break;
1151 if ((labelSplit_RemainingCharsAfterSplit - tmp_checkoffs) < 0)
1153 #if defined(DEBUG_ILC_ICONRENDERING)
1154 D(bug("="));
1155 #endif
1156 labelSplit_CurSplitLength = labelSplit_CurSplitLength + tmp_checkoffs;
1157 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit + tmp_checkoffs;
1158 tmp_checkoffs = 0;
1159 break;
1162 if ((labelSplit_RemainingCharsAfterSplit - tmp_checkoffs) >= ILC_ICONLABEL_SHORTEST)
1164 #if defined(DEBUG_ILC_ICONRENDERING)
1165 D(bug(">"));
1166 #endif
1167 if ((*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == ' ') ||
1168 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == '.') ||
1169 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == '-'))
1171 #if defined(DEBUG_ILC_ICONRENDERING)
1172 D(bug("!"));
1173 #endif
1174 labelSplit_CurSplitLength = labelSplit_CurSplitLength + tmp_checkoffs;
1175 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit + tmp_checkoffs;
1176 tmp_checkoffs = 0;
1177 break;
1181 tmp_checkoffs = tmp_checkoffs + 1;
1183 #if defined(DEBUG_ILC_ICONRENDERING)
1184 D(bug("\n"));
1185 #endif
1186 if (tmp_checkoffs != 0)
1188 #if defined(DEBUG_ILC_ICONRENDERING)
1189 D(bug("[IconList]: %s: Couldnt find neat split : Still %d chars\n", __PRETTY_FUNCTION__, labelSplit_RemainingCharsAfterSplit));
1190 #endif
1191 if (labelSplit_RemainingCharsAfterSplit <= ILC_ICONLABEL_SHORTEST)
1193 labelSplit_CurSplitLength = labelSplit_CurSplitLength + (labelSplit_RemainingCharsAfterSplit - ILC_ICONLABEL_SHORTEST);
1196 if ((labelSplit_CharsDone + labelSplit_CurSplitLength) > labelSplit_LabelLength) labelSplit_CurSplitLength = labelSplit_LabelLength - labelSplit_CharsDone;
1198 if (entry->ie_TxtBuf_DisplayedLabel != NULL)
1200 labelSplit_CurSplitDest = (IPTR)(entry->ie_TxtBuf_DisplayedLabel
1201 + labelSplit_CharsSplit + entry->ie_SplitParts);
1203 strncpy((char *)labelSplit_CurSplitDest,
1204 (char *)labelSplit_SplitStart, labelSplit_CurSplitLength);
1206 labelSplit_CurSplitWidth = TextLength(data->icld_BufferRastPort,
1207 (char *)labelSplit_CurSplitDest, labelSplit_CurSplitLength);
1210 entry->ie_SplitParts = entry->ie_SplitParts + 1;
1212 labelSplit_CharsDone = labelSplit_CharsDone + labelSplit_CurSplitLength;
1213 labelSplit_CharsSplit = labelSplit_CharsSplit + labelSplit_CurSplitLength;
1215 if (labelSplit_CurSplitWidth > entry->ie_TxtBuf_DisplayedLabelWidth) entry->ie_TxtBuf_DisplayedLabelWidth = labelSplit_CurSplitWidth;
1217 if ((entry->ie_SplitParts <= 1) && entry->ie_TxtBuf_DisplayedLabel)
1219 FreeVecPooled(data->icld_Pool, entry->ie_TxtBuf_DisplayedLabel);
1220 entry->ie_TxtBuf_DisplayedLabel = NULL;
1221 entry->ie_SplitParts = 0;
1223 // if ((labelSplit_FontY * entry->ie_SplitParts) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = (labelSplit_FontY * entry->ie_SplitParts);
1227 ///IconList__LabelFunc_CreateLabel()
1228 static IPTR IconList__LabelFunc_CreateLabel(Object *obj, struct IconList_DATA *data, struct IconEntry *entry)
1230 #if defined(DEBUG_ILC_ICONRENDERING) || defined(DEBUG_ILC_FUNCS)
1231 D(bug("[IconList]: %s('%s')\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label));
1232 #endif
1233 if (entry->ie_TxtBuf_DisplayedLabel)
1235 FreeVecPooled(data->icld_Pool, entry->ie_TxtBuf_DisplayedLabel);
1236 entry->ie_TxtBuf_DisplayedLabel = NULL;
1237 entry->ie_SplitParts = 0;
1240 if (data->icld__Option_LabelTextMultiLine > 1)
1242 #if defined(DEBUG_ILC_ICONRENDERING)
1243 D(bug("[IconList]: %s: Attempting to split label ..\n", __PRETTY_FUNCTION__));
1244 #endif
1245 IconList__LabelFunc_SplitLabel(obj, data, entry);
1248 if (entry->ie_TxtBuf_DisplayedLabel == NULL)
1250 ULONG ie_LabelLength = strlen(entry->ie_IconListEntry.label);
1251 entry->ie_SplitParts = 1;
1253 #if defined(DEBUG_ILC_ICONRENDERING)
1254 D(bug("[IconList]: %s: Building unsplit label (len = %d) ..\n", __PRETTY_FUNCTION__, ie_LabelLength));
1255 #endif
1257 if ((data->icld__Option_TrimVolumeNames) &&
1258 ((entry->ie_IconListEntry.type == ST_ROOT) && (entry->ie_IconListEntry.label[ie_LabelLength - 1] == ':')))
1259 ie_LabelLength--;
1261 if(ie_LabelLength > data->icld__Option_LabelTextMaxLen)
1263 if (!(entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, data->icld__Option_LabelTextMaxLen + 1)))
1265 return (IPTR)NULL;
1267 memset(entry->ie_TxtBuf_DisplayedLabel, 0, data->icld__Option_LabelTextMaxLen + 1);
1268 strncpy(entry->ie_TxtBuf_DisplayedLabel, entry->ie_IconListEntry.label, data->icld__Option_LabelTextMaxLen - 3);
1269 strcat(entry->ie_TxtBuf_DisplayedLabel , " ..");
1271 else
1273 if (!(entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, ie_LabelLength + 1)))
1275 return (IPTR)NULL;
1277 memset(entry->ie_TxtBuf_DisplayedLabel, 0, ie_LabelLength + 1);
1278 strncpy(entry->ie_TxtBuf_DisplayedLabel, entry->ie_IconListEntry.label, ie_LabelLength );
1280 entry->ie_TxtBuf_DisplayedLabelWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_DisplayedLabel, strlen(entry->ie_TxtBuf_DisplayedLabel));
1281 // if ((data->icld_IconLabelFont->tf_YSize) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = data->icld_IconLabelFont->tf_YSize;
1284 // if (entry->ie_TxtBuf_DisplayedLabelWidth > data->icld_LabelLargestWidth) data->icld_LabelLargestWidth = entry->ie_TxtBuf_DisplayedLabelWidth;
1286 return (IPTR)entry->ie_TxtBuf_DisplayedLabel;
1290 ///IconList__HookFunc_UpdateLabelsFunc()
1291 AROS_UFH3(
1292 void, IconList__HookFunc_UpdateLabelsFunc,
1293 AROS_UFHA(struct Hook *, hook, A0),
1294 AROS_UFHA(APTR *, obj, A2),
1295 AROS_UFHA(APTR, param, A1)
1298 AROS_USERFUNC_INIT
1300 /* Get our private data */
1301 Class *CLASS = *( Class **)param;
1302 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1304 #if defined(DEBUG_ILC_LASSO) || defined(DEBUG_ILC_FUNCS)
1305 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1306 #endif
1308 if (((data->icld__Option_LabelTextMaxLen != data->icld__Option_LastLabelTextMaxLen) &&
1309 (data->icld__Option_LabelTextMultiLine > 1)) ||
1310 (data->icld__Option_LabelTextMultiLine != data->icld__Option_LastLabelTextMultiLine));
1312 struct IconEntry *iconentry_Current = NULL;
1313 #if defined(__AROS__)
1314 ForeachNode(&data->icld_IconList, iconentry_Current)
1315 #else
1316 Foreach_Node(&data->icld_IconList, iconentry_Current);
1317 #endif
1319 IconList__LabelFunc_CreateLabel((Object *)obj, data, iconentry_Current);
1323 data->icld__Option_LastLabelTextMaxLen = data->icld__Option_LabelTextMaxLen;
1324 data->icld__Option_LastLabelTextMultiLine = data->icld__Option_LabelTextMultiLine;
1326 AROS_USERFUNC_EXIT
1330 ///IconList__MUIM_IconList_DrawEntryLabel()
1331 IPTR IconList__MUIM_IconList_DrawEntryLabel(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DrawEntry *message)
1333 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1335 STRPTR buf = NULL;
1336 BOOL outside = FALSE;
1338 struct Rectangle iconlabelrect;
1339 struct Rectangle objrect;
1341 ULONG txtbox_width = 0;
1342 LONG tx,ty,offsetx,offsety;
1343 LONG txwidth; // txheight;
1345 ULONG objX, objY, objW, objH;
1346 LONG labelX, labelY;
1348 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1349 return FALSE;
1351 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
1353 objX = _mleft(obj);
1354 objY = _mtop(obj);
1356 else
1358 objX = objY = 0;
1360 objW = _mright(obj) - _mleft(obj) + 1;
1361 objH = _mbottom(obj) - _mtop(obj) + 1;
1363 ULONG txtarea_width;
1364 ULONG curlabel_TotalLines, curlabel_CurrentLine, offset_y;
1366 #if defined(DEBUG_ILC_ICONRENDERING) || defined(DEBUG_ILC_FUNCS)
1367 D(bug("[IconList]: %s(message->entry = 0x%p), '%s'\n", __PRETTY_FUNCTION__, message->entry, message->entry->ie_IconListEntry.label));
1368 #endif
1370 if ((!(message->entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)) ||
1371 (data->icld_BufferRastPort == NULL) ||
1372 (!(message->entry->ie_DiskObj)))
1374 #if defined(DEBUG_ILC_ICONRENDERING)
1375 D(bug("[IconList] %s: Not visible or missing DOB\n", __PRETTY_FUNCTION__));
1376 #endif
1377 return FALSE;
1380 /* Get the dimensions and affected area of message->entry's label */
1381 IconList_GetIconLabelRectangle(obj, data, message->entry, &iconlabelrect);
1383 /* Add the relative position offset of the message->entry's label */
1384 offsetx = (objX - data->icld_ViewX) + message->entry->ie_IconX;
1385 txtbox_width = (iconlabelrect.MaxX - iconlabelrect.MinX) + 1;
1387 if (txtbox_width < message->entry->ie_AreaWidth)
1388 offsetx += ((message->entry->ie_AreaWidth - txtbox_width)/2);
1390 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1391 (message->entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
1392 offsetx += ((data->icld_IconAreaLargestWidth - message->entry->ie_AreaWidth)/2);
1394 iconlabelrect.MinX += offsetx;
1395 iconlabelrect.MaxX += offsetx;
1397 offsety = (objY - data->icld_ViewY) + message->entry->ie_IconY + data->icld__Option_IconImageSpacing;
1398 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1399 (message->entry->ie_AreaHeight < data->icld_IconAreaLargestHeight))
1400 offsety += ((data->icld_IconAreaLargestHeight - message->entry->ie_AreaHeight)/2);
1402 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1404 offsety = offsety + data->icld_IconLargestHeight;
1406 else
1408 offsety = offsety + message->entry->ie_IconHeight;
1410 iconlabelrect.MinY += offsety;
1411 iconlabelrect.MaxY += offsety;
1413 /* Add the relative position of the window */
1414 objrect.MinX = objX;
1415 objrect.MinY = objX;
1416 objrect.MaxX = objX + objW;
1417 objrect.MaxY = objY + objH;
1419 if (!RectAndRect(&iconlabelrect, &objrect))
1421 #if defined(DEBUG_ILC_ICONRENDERING)
1422 (bug("[IconList] %s: Entry '%s' label outside of visible area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1423 #endif
1424 return FALSE;
1427 /* data->update_rect1 and data->update_rect2 may
1428 point to rectangles to indicate that only icons
1429 in any of this rectangles need to be drawn */
1430 if (data->update_rect1)
1432 if (!RectAndRect(&iconlabelrect, data->update_rect1))
1433 outside = TRUE;
1436 if (data->update_rect2)
1438 if (data->update_rect1)
1440 if ((outside == TRUE) && RectAndRect(&iconlabelrect, data->update_rect2))
1441 outside = FALSE;
1443 else
1445 if (!RectAndRect(&iconlabelrect, data->update_rect2))
1446 outside = TRUE;
1450 if (outside == TRUE)
1452 #if defined(DEBUG_ILC_ICONRENDERING)
1453 D(bug("[IconList] %s: Entry '%s' label outside of update area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1454 #endif
1455 return FALSE;
1458 if (message->drawmode == ICONENTRY_DRAWMODE_NONE)
1459 return TRUE;
1461 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_TEXT], 0, JAM1);
1463 iconlabelrect.MinX = (iconlabelrect.MinX - objX) + data->icld_DrawOffsetX;
1464 iconlabelrect.MinY = (iconlabelrect.MinY - objY) + data->icld_DrawOffsetY;
1465 iconlabelrect.MaxX = (iconlabelrect.MaxX - objX) + data->icld_DrawOffsetX;
1466 iconlabelrect.MaxY = (iconlabelrect.MaxY - objY) + data->icld_DrawOffsetY;
1468 labelX = iconlabelrect.MinX + data->icld__Option_LabelTextBorderWidth + data->icld__Option_LabelTextHorizontalPadding;
1469 labelY = iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight + data->icld__Option_LabelTextVerticalPadding;
1471 txtarea_width = txtbox_width - ((data->icld__Option_LabelTextBorderWidth + data->icld__Option_LabelTextHorizontalPadding) * 2);
1473 #if defined(DEBUG_ILC_ICONRENDERING)
1474 D(bug("[IconList] %s: Drawing Label '%s' .. %d, %d\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label, labelX, labelY));
1475 #endif
1476 if (message->entry->ie_IconListEntry.label && message->entry->ie_TxtBuf_DisplayedLabel)
1478 char *curlabel_StrPtr;
1480 if ((message->entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
1482 //Draw the focus box around the selected label ..
1483 if (data->icld__Option_LabelTextBorderHeight > 0)
1485 InvertPixelArray(data->icld_BufferRastPort,
1486 iconlabelrect.MinX, iconlabelrect.MinY,
1487 (iconlabelrect.MaxX - iconlabelrect.MinX) + 1, data->icld__Option_LabelTextBorderHeight);
1489 InvertPixelArray(data->icld_BufferRastPort,
1490 iconlabelrect.MinX, iconlabelrect.MaxY - (data->icld__Option_LabelTextBorderHeight - 1),
1491 (iconlabelrect.MaxX - iconlabelrect.MinX) + 1, data->icld__Option_LabelTextBorderHeight);
1493 if (data->icld__Option_LabelTextBorderWidth > 0)
1495 InvertPixelArray(data->icld_BufferRastPort,
1496 iconlabelrect.MinX, iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight,
1497 data->icld__Option_LabelTextBorderWidth, (((iconlabelrect.MaxY - iconlabelrect.MinY) + 1) - (data->icld__Option_LabelTextBorderHeight * 2)));
1499 InvertPixelArray(data->icld_BufferRastPort,
1500 iconlabelrect.MaxX - (data->icld__Option_LabelTextBorderWidth - 1), iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight,
1501 data->icld__Option_LabelTextBorderWidth, (((iconlabelrect.MaxY - iconlabelrect.MinY) + 1) - (data->icld__Option_LabelTextBorderHeight * 2)));
1505 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
1507 curlabel_TotalLines = message->entry->ie_SplitParts;
1508 curlabel_CurrentLine = 0;
1510 if (curlabel_TotalLines == 0)
1511 curlabel_TotalLines = 1;
1513 if (!(data->icld__Option_LabelTextMultiLineOnFocus) || (data->icld__Option_LabelTextMultiLineOnFocus && (message->entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
1515 if (curlabel_TotalLines > data->icld__Option_LabelTextMultiLine)
1516 curlabel_TotalLines = data->icld__Option_LabelTextMultiLine;
1518 else
1519 curlabel_TotalLines = 1;
1521 curlabel_StrPtr = message->entry->ie_TxtBuf_DisplayedLabel;
1523 ty = labelY - 1;
1525 #if defined(DEBUG_ILC_ICONRENDERING)
1526 D(bug("[IconList] %s: Font YSize %d Baseline %d\n", __PRETTY_FUNCTION__,data->icld_IconLabelFont->tf_YSize, data->icld_IconLabelFont->tf_Baseline));
1527 #endif
1528 for (curlabel_CurrentLine = 0; curlabel_CurrentLine < curlabel_TotalLines; curlabel_CurrentLine++)
1530 ULONG ie_LabelLength;
1532 if (curlabel_CurrentLine > 0) curlabel_StrPtr = curlabel_StrPtr + strlen(curlabel_StrPtr) + 1;
1533 if ((curlabel_CurrentLine >= (curlabel_TotalLines -1)) && (curlabel_TotalLines < message->entry->ie_SplitParts))
1535 char *tmpLine = curlabel_StrPtr;
1536 ULONG tmpLen = strlen(tmpLine);
1538 if ((curlabel_StrPtr = AllocVecPooled(data->icld_Pool, tmpLen + 1)) != NULL)
1540 memset(curlabel_StrPtr, 0, tmpLen + 1);
1541 strncpy(curlabel_StrPtr, tmpLine, tmpLen - 3);
1542 strcat(curlabel_StrPtr , " ..");
1544 else
1545 return FALSE;
1549 ie_LabelLength = strlen(curlabel_StrPtr);
1550 offset_y = 0;
1552 // Center message->entry's label
1553 tx = (labelX + (message->entry->ie_TxtBuf_DisplayedLabelWidth / 2) - (TextLength(data->icld_BufferRastPort, curlabel_StrPtr, strlen(curlabel_StrPtr)) / 2));
1555 if (message->entry->ie_TxtBuf_DisplayedLabelWidth < txtarea_width)
1556 tx += ((txtarea_width - message->entry->ie_TxtBuf_DisplayedLabelWidth)/2);
1558 ty = ty + data->icld_IconLabelFont->tf_YSize;
1560 switch ( data->icld__Option_LabelTextMode )
1562 case ICON_TEXTMODE_DROPSHADOW:
1563 SetAPen(data->icld_BufferRastPort, data->icld_LabelShadowPen);
1564 Move(data->icld_BufferRastPort, tx + 1, ty + 1);
1565 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1566 offset_y = 1;
1567 case ICON_TEXTMODE_PLAIN:
1568 SetAPen(data->icld_BufferRastPort, data->icld_LabelPen);
1569 Move(data->icld_BufferRastPort, tx, ty);
1570 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1571 break;
1573 default:
1574 // Outline mode:
1575 SetSoftStyle(data->icld_BufferRastPort, FSF_BOLD, AskSoftStyle(data->icld_BufferRastPort));
1577 SetAPen(data->icld_BufferRastPort, data->icld_LabelShadowPen);
1578 Move(data->icld_BufferRastPort, tx + 1, ty );
1579 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1580 Move(data->icld_BufferRastPort, tx - 1, ty );
1581 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1582 Move(data->icld_BufferRastPort, tx, ty + 1);
1583 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1584 Move(data->icld_BufferRastPort, tx, ty - 1);
1585 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1587 SetAPen(data->icld_BufferRastPort, data->icld_LabelPen);
1588 Move(data->icld_BufferRastPort, tx , ty );
1589 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1591 SetSoftStyle(data->icld_BufferRastPort, FS_NORMAL, AskSoftStyle(data->icld_BufferRastPort));
1592 offset_y = 2;
1593 break;
1595 if ((curlabel_CurrentLine >= (curlabel_TotalLines -1)) && (curlabel_TotalLines < message->entry->ie_SplitParts))
1597 FreeVecPooled(data->icld_Pool, curlabel_StrPtr);
1599 ty = ty + offset_y;
1602 /*date/size sorting has the date/size appended under the message->entry label*/
1604 if ((message->entry->ie_IconListEntry.type != ST_USERDIR) && ((data->icld_SortFlags & (MUIV_IconList_Sort_BySize|MUIV_IconList_Sort_ByDate)) != 0))
1606 buf = NULL;
1607 SetFont(data->icld_BufferRastPort, data->icld_IconInfoFont);
1609 if (data->icld_SortFlags & MUIV_IconList_Sort_BySize)
1611 buf = message->entry->ie_TxtBuf_SIZE;
1612 txwidth = message->entry->ie_TxtBuf_SIZEWidth;
1614 else if (data->icld_SortFlags & MUIV_IconList_Sort_ByDate)
1616 if (message->entry->ie_Flags & ICONENTRY_FLAG_TODAY)
1618 buf = message->entry->ie_TxtBuf_TIME;
1619 txwidth = message->entry->ie_TxtBuf_TIMEWidth;
1621 else
1623 buf = message->entry->ie_TxtBuf_DATE;
1624 txwidth = message->entry->ie_TxtBuf_DATEWidth;
1628 if (buf)
1630 ULONG ie_LabelLength = strlen(buf);
1631 tx = labelX;
1633 if (txwidth < txtarea_width)
1634 tx += ((txtarea_width - txwidth)/2);
1636 ty = labelY + ((data->icld__Option_LabelTextVerticalPadding + data->icld_IconLabelFont->tf_YSize ) * curlabel_TotalLines) + data->icld_IconInfoFont->tf_YSize;
1638 switch ( data->icld__Option_LabelTextMode )
1640 case ICON_TEXTMODE_DROPSHADOW:
1641 SetAPen(data->icld_BufferRastPort, data->icld_InfoShadowPen);
1642 Move(data->icld_BufferRastPort, tx + 1, ty + 1); Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1643 case ICON_TEXTMODE_PLAIN:
1644 SetAPen(data->icld_BufferRastPort, data->icld_InfoPen);
1645 Move(data->icld_BufferRastPort, tx, ty); Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1646 break;
1648 default:
1649 // Outline mode..
1650 SetSoftStyle(data->icld_BufferRastPort, FSF_BOLD, AskSoftStyle(data->icld_BufferRastPort));
1651 SetAPen(data->icld_BufferRastPort, data->icld_InfoShadowPen);
1653 Move(data->icld_BufferRastPort, tx + 1, ty );
1654 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1655 Move(data->icld_BufferRastPort, tx - 1, ty );
1656 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1657 Move(data->icld_BufferRastPort, tx, ty - 1 );
1658 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1659 Move(data->icld_BufferRastPort, tx, ty + 1 );
1660 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1662 SetAPen(data->icld_BufferRastPort, data->icld_InfoPen);
1664 Move(data->icld_BufferRastPort, tx, ty );
1665 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1667 SetSoftStyle(data->icld_BufferRastPort, FS_NORMAL, AskSoftStyle(data->icld_BufferRastPort));
1668 break;
1674 return TRUE;
1677 /**************************************************************************
1679 **************************************************************************/
1680 ///IconList__MUIM_IconList_RethinkDimensions()
1681 IPTR IconList__MUIM_IconList_RethinkDimensions(struct IClass *CLASS, Object *obj, struct MUIP_IconList_RethinkDimensions *message)
1683 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1685 struct IconEntry *entry = NULL;
1686 LONG maxx = 0,
1687 maxy = 0;
1688 struct Rectangle icon_rect;
1690 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
1691 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1692 #endif
1694 if (message->singleicon != NULL)
1696 entry = message->singleicon;
1697 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1699 maxy = data->icld_LVMAttribs->lmva_RowHeight;
1700 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
1702 maxy += data->icld_LVMAttribs->lmva_HeaderHeight;
1705 else
1707 maxx = data->icld_AreaWidth - 1,
1708 maxy = data->icld_AreaHeight - 1;
1711 #if defined(DEBUG_ILC_ICONPOSITIONING)
1712 D(bug("[IconList] %s: SingleIcon - maxx = %d, maxy = %d\n", __PRETTY_FUNCTION__, maxx, maxy));
1713 #endif
1715 else
1717 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1719 maxy = data->icld_LVMAttribs->lmva_RowHeight;
1720 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
1722 maxy += data->icld_LVMAttribs->lmva_HeaderHeight;
1725 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1728 while (entry != NULL)
1730 if (entry->ie_DiskObj &&
1731 (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1733 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1735 maxy += data->icld_LVMAttribs->lmva_RowHeight;
1737 else
1739 IconList_GetIconAreaRectangle(obj, data, entry, &icon_rect);
1741 icon_rect.MaxX += entry->ie_IconX + data->icld__Option_IconHorizontalSpacing;
1742 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1743 (entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
1744 icon_rect.MaxX += (data->icld_IconAreaLargestWidth - entry->ie_AreaWidth);
1746 icon_rect.MaxY += entry->ie_IconY + data->icld__Option_IconVerticalSpacing;
1748 if (icon_rect.MaxX > maxx) maxx = icon_rect.MaxX;
1749 if (icon_rect.MaxY > maxy) maxy = icon_rect.MaxY;
1753 if (message->singleicon)
1754 break;
1756 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
1759 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1761 int col;
1763 for(col = 0; col < NUM_COLUMNS; col++)
1765 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[col];
1767 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
1769 maxx += data->icld_LVMAttribs->lmva_ColumnWidth[index];
1773 /* update our view when max x/y have changed */
1774 if (maxx + 1 != data->icld_AreaWidth)
1776 data->icld_AreaWidth = maxx + 1;
1777 SET(obj, MUIA_IconList_Width, data->icld_AreaWidth);
1779 if (maxy + 1 != data->icld_AreaHeight)
1781 data->icld_AreaHeight = maxy + 1;
1782 SET(obj, MUIA_IconList_Height, data->icld_AreaHeight);
1785 return TRUE;
1789 * This function executes the layouting when AutoSort is enabled. This means all icons are layouted regardless if
1790 * they have Provided position or not.
1793 static VOID IconList_Layout_FullAutoLayout(struct IClass *CLASS, Object *obj)
1795 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1796 struct IconEntry *entry = NULL;
1797 struct IconEntry *pass_first = NULL; /* First entry of current column or row */
1799 LONG left = data->icld__Option_IconHorizontalSpacing;
1800 LONG top = data->icld__Option_IconVerticalSpacing;
1801 LONG cur_x = left;
1802 LONG cur_y = top;
1803 LONG gridx = 0;
1804 LONG gridy = 0;
1805 LONG maxw = 0; /* Widest & talest entry in a column or row */
1806 LONG maxh = 0;
1808 BOOL calcnextpos;
1809 struct Rectangle iconrect;
1811 /* Now go to the actual positioning */
1812 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1813 while (entry != NULL)
1815 calcnextpos = FALSE;
1816 if ((entry->ie_DiskObj != NULL) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1818 calcnextpos = TRUE;
1820 /* Set previously calculated position to this icon */
1821 entry->ie_IconX = cur_x;
1822 entry->ie_IconY = cur_y;
1824 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
1826 if (data->icld_SelectionLastClicked == NULL) data->icld_SelectionLastClicked = entry;
1827 if (data->icld_FocusIcon == NULL) data->icld_FocusIcon = entry;
1830 /* Calculate grid size to advanced the coordinate in next step */
1831 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1833 maxw = data->icld_IconAreaLargestWidth + data->icld__Option_IconHorizontalSpacing;
1834 maxh = data->icld_IconLargestHeight + data->icld__Option_IconImageSpacing + data->icld_LabelLargestHeight + data->icld__Option_IconVerticalSpacing;
1835 gridx = maxw;
1836 gridy = maxh;
1838 else
1840 if (!(pass_first)) pass_first = entry;
1842 IconList_GetIconAreaRectangle(obj, data, entry, &iconrect);
1844 if ((maxw < entry->ie_AreaWidth) || (maxh < entry->ie_AreaHeight))
1846 if (maxw < entry->ie_AreaWidth) maxw = entry->ie_AreaWidth;
1847 if (maxh < entry->ie_AreaHeight) maxh = entry->ie_AreaHeight;
1848 if (pass_first != entry)
1850 entry = pass_first;
1851 cur_x = entry->ie_IconX;
1852 cur_y = entry->ie_IconY;
1853 /* We detected that the new icon it taller/wider than icons so far in this row/column.
1854 * We need to re-layout this row/column. */
1855 continue;
1859 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1861 /* Centering */
1862 if (entry->ie_AreaWidth < maxw)
1863 entry->ie_IconX += ( maxw - entry->ie_AreaWidth ) / 2;
1865 gridx = maxw;
1866 gridy = entry->ie_AreaHeight + data->icld__Option_IconVerticalSpacing;
1868 else
1870 /* Centering */ /* Icons look better not centered in this case - disabled */
1871 /* if (entry->ie_AreaHeight < maxh)
1872 entry->ie_IconY += ( maxh - entry->ie_AreaHeight ) / 2; */
1874 gridx = entry->ie_AreaWidth + data->icld__Option_IconHorizontalSpacing;
1875 gridy = maxh;
1881 * Advance to next icon and calculate its position based on grid sizes from previous step.
1882 * Don't set position - it is done at beginning of the loop.
1884 if ((entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode)) != NULL)
1886 if (calcnextpos)
1888 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1890 cur_y += gridy;
1892 if ((cur_y >= data->icld_ViewHeight) ||
1893 ((data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH) && ((cur_y + entry->ie_AreaHeight - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight)) ||
1894 ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) && ((cur_y + data->icld_IconAreaLargestHeight - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight)))
1896 /* Wrap "around" if the icon would be below bottom border */
1897 cur_x += maxw;
1898 cur_y = top;
1899 pass_first = NULL;
1900 maxw = 0;
1903 else
1905 cur_x += gridx;
1907 if ((cur_x >= data->icld_ViewWidth) ||
1908 ((data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH) && ((cur_x + entry->ie_AreaWidth - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth)) ||
1909 ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) && ((cur_x + data->icld_IconAreaLargestWidth - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth)))
1911 /* Wrap "around" if the icon would be right of right border */
1912 cur_x = left;
1913 cur_y += maxh;
1914 pass_first = NULL;
1915 maxh = 0;
1923 static VOID IconList_Layout_PartialAutoLayout(struct IClass *CLASS, Object *obj)
1925 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1926 struct Region *occupied = NewRegion();
1927 struct IconEntry *entry = NULL;
1928 LONG left = data->icld__Option_IconHorizontalSpacing;
1929 LONG top = data->icld__Option_IconVerticalSpacing;
1930 LONG cur_x = left, cur_y = top;
1932 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1933 while (entry != NULL)
1935 if ((entry->ie_ProvidedIconX != NO_ICON_POSITION) && (entry->ie_ProvidedIconY != NO_ICON_POSITION)
1936 && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1938 struct Rectangle iconrect = {
1939 entry->ie_ProvidedIconX,
1940 entry->ie_ProvidedIconY,
1941 entry->ie_ProvidedIconX + entry->ie_AreaWidth - 1,
1942 entry->ie_ProvidedIconY + entry->ie_AreaHeight - 1
1945 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1946 iconrect.MaxY += data->icld__Option_IconVerticalSpacing;
1947 else
1948 iconrect.MaxX += data->icld__Option_IconHorizontalSpacing;
1950 D(bug("Adding %s (%d %d)(%d %d)\n", entry->ie_TxtBuf_DisplayedLabel,
1951 (LONG)iconrect.MinX, (LONG)iconrect.MinY, (LONG)iconrect.MaxX, (LONG)iconrect.MaxY));
1953 OrRectRegion(occupied, &iconrect);
1955 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
1958 /* Now go to the actual positioning */
1959 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1960 while (entry != NULL)
1962 if ((entry->ie_DiskObj != NULL) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1964 if ((entry->ie_ProvidedIconX != NO_ICON_POSITION) && (entry->ie_ProvidedIconY != NO_ICON_POSITION))
1966 entry->ie_IconX = entry->ie_ProvidedIconX;
1967 entry->ie_IconY = entry->ie_ProvidedIconY;
1969 else
1971 LONG gridx, gridy, stepx = 0, stepy = 0, addx = 0;
1972 struct Rectangle iconarea;
1973 BOOL first = TRUE;
1975 /* Calculate grid size and step */
1976 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1978 gridx = data->icld_IconAreaLargestWidth + data->icld__Option_IconHorizontalSpacing;
1979 gridy = data->icld_IconLargestHeight + data->icld__Option_IconImageSpacing + data->icld_LabelLargestHeight + data->icld__Option_IconVerticalSpacing;
1981 else
1983 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1985 gridx = data->icld_IconAreaLargestWidth; /* This gives better centering effect */
1986 gridy = entry->ie_AreaHeight + data->icld__Option_IconVerticalSpacing;
1987 addx = (gridx - entry->ie_AreaWidth) / 2;
1989 else
1991 gridx = entry->ie_AreaWidth + data->icld__Option_IconHorizontalSpacing;
1992 gridy = entry->ie_AreaHeight + data->icld__Option_IconVerticalSpacing;
1996 /* Find first not occupied spot matching the calculate rectangle */
1999 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
2001 /* Overwrite value set via RegionAndRect */
2002 stepx = gridx;
2003 stepy = gridy;
2006 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
2008 /* Advance to next position */
2009 if (!first) cur_y += stepy;
2011 if ((cur_y >= data->icld_ViewHeight) ||
2012 ((cur_y + gridy - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight))
2014 /* Wrap "around" if the icon would be below bottom border */
2015 cur_x += gridx;
2016 cur_y = top;
2019 else
2021 /* Advance to next position */
2022 if (!first) cur_x += stepx;
2024 if ((cur_x >= data->icld_ViewWidth) ||
2025 ((cur_x + gridx - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth))
2027 /* Wrap "around" if the icon would be right of right border */
2028 cur_x = left;
2029 cur_y += gridy;
2033 iconarea.MinX = cur_x;
2034 iconarea.MinY = cur_y;
2035 iconarea.MaxX = cur_x + gridx - 1;
2036 iconarea.MaxY = cur_y + gridy - 1;
2038 first = FALSE;
2040 } while(RegionAndRect(occupied, &iconarea, &stepx, &stepy));
2042 entry->ie_IconX = iconarea.MinX + addx;
2043 entry->ie_IconY = iconarea.MinY;
2045 /* Add this area to occupied list */
2046 OrRectRegion(occupied, &iconarea);
2048 /* Add spacing to next icon */
2049 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
2050 cur_y += gridy;
2051 else
2052 cur_x += gridx;
2056 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
2059 DisposeRegion(occupied);
2063 ///IconList__MUIM_IconList_PositionIcons()
2064 /**************************************************************************
2065 MUIM_PositionIcons - Place icons with NO_ICON_POSITION coords somewhere
2066 **************************************************************************/
2067 IPTR IconList__MUIM_IconList_PositionIcons(struct IClass *CLASS, Object *obj, struct MUIP_IconList_PositionIcons *message)
2069 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2070 struct IconEntry *entry = NULL;
2073 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
2074 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2075 #endif
2076 if ((data->icld_SortFlags & MUIV_IconList_Sort_AutoSort) == 0)
2078 IconList_Layout_PartialAutoLayout(CLASS, obj);
2080 else
2082 IconList_Layout_FullAutoLayout(CLASS, obj);
2086 * Set Provided icon position on all icons (this can't be done as part of previous loop!)
2087 * The icons will not no longer be autolayouted unless MUIV_IconList_Sort_AutoSort is set.
2088 * This give the stability that new icons appearing won't make existing icons jump from their places
2090 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
2091 while (entry != NULL)
2093 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
2094 DoMethod(obj, MUIM_IconList_PropagateEntryPos, entry);
2096 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
2100 DoMethod(obj, MUIM_IconList_RethinkDimensions, NULL);
2101 return (IPTR)NULL;
2105 ///OM_NEW()
2107 #define ICONENTRY_SIZE 16
2109 static inline void CalcHeight(struct ListViewModeAttribs *LVMAttribs, struct TextFont *LabelFont)
2111 ULONG YSize = LabelFont ? LabelFont->tf_YSize : 0;
2113 LVMAttribs->lmva_HeaderHeight = HEADERLINE_EXTRAHEIGHT + YSize;
2114 LVMAttribs->lmva_RowHeight = LINE_EXTRAHEIGHT + ((ICONENTRY_SIZE > YSize) ? ICONENTRY_SIZE : YSize);
2117 /**************************************************************************
2118 OM_NEW
2119 **************************************************************************/
2120 IPTR IconList__OM_NEW(struct IClass *CLASS, Object *obj, struct opSet *message)
2122 struct IconList_DATA *data = NULL;
2123 struct TextFont *icl_WindowFont = NULL;
2124 // struct RastPort *icl_RastPort = NULL;
2125 int i;
2127 #if defined(DEBUG_ILC_FUNCS)
2128 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2129 #endif
2131 icl_WindowFont = (struct TextFont *) GetTagData(MUIA_Font, (IPTR) NULL, message->ops_AttrList);
2133 obj = (Object *)DoSuperNewTags(CLASS, obj, NULL,
2134 MUIA_FillArea, FALSE,
2135 MUIA_Dropable, TRUE,
2136 MUIA_Font, MUIV_Font_Tiny,
2137 TAG_MORE, (IPTR) message->ops_AttrList);
2139 if (!obj) return FALSE;
2141 data = INST_DATA(CLASS, obj);
2143 data->icld_Pool = CreatePool(0,4096,4096);
2144 if (!data->icld_Pool)
2146 CoerceMethod(CLASS,obj,OM_DISPOSE);
2147 return (IPTR)NULL;
2150 #if defined(DEBUG_ILC_FUNCS)
2151 D(bug("[IconList] %s: SELF = 0x%p, muiRenderInfo = 0x%p\n", __PRETTY_FUNCTION__, obj, muiRenderInfo(obj)));
2152 #endif
2153 NewList((struct List*)&data->icld_IconList);
2154 NewList((struct List*)&data->icld_SelectionList);
2156 data->icld_IconLabelFont = icl_WindowFont;
2158 /* Setup List View-Mode options */
2159 if ((data->icld_LVMAttribs = AllocMem(sizeof(struct ListViewModeAttribs), MEMF_CLEAR)) != NULL)
2161 for(i = 0; i < NUM_COLUMNS; i++)
2163 data->icld_LVMAttribs->lmva_ColumnPos[i] = i;
2164 data->icld_LVMAttribs->lmva_ColumnFlags[i] = LVMCF_COLVISIBLE;
2165 data->icld_LVMAttribs->lmva_ColumnWidth[i] = 100;
2166 data->icld_LVMAttribs->lmva_ColumnHAlign[i] = COLUMN_ALIGN_LEFT;
2167 switch (i)
2169 case INDEX_TYPE:
2170 data->icld_LVMAttribs->lmva_ColumnHAlign[i] = COLUMN_ALIGN_RIGHT;
2171 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= (LVMCF_COLCLICKABLE|LVMCF_COLSORTABLE);
2172 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Type";
2173 data->icld_LVMAttribs->lmva_ColumnWidth[i] = ICONENTRY_SIZE + 2;
2174 break;
2176 case INDEX_NAME:
2177 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= (LVMCF_COLCLICKABLE|LVMCF_COLSORTABLE);
2178 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Name";
2179 break;
2181 case INDEX_SIZE:
2182 data->icld_LVMAttribs->lmva_ColumnHAlign[i] = COLUMN_ALIGN_RIGHT;
2183 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= LVMCF_COLSORTABLE;
2184 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Size";
2185 break;
2187 case INDEX_LASTACCESS:
2188 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= LVMCF_COLSORTABLE;
2189 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Last Accessed";
2190 break;
2192 case INDEX_COMMENT:
2193 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Comment";
2194 break;
2196 case INDEX_PROTECTION:
2197 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Protection";
2198 break;
2200 default:
2201 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "<Unknown>";
2202 break;
2205 data->icld_LVMAttribs->lmva_LastSelectedColumn = -1;
2206 data->icld_LVMAttribs->lmva_SortColumn = INDEX_NAME;
2207 data->icld_LVMAttribs->lvma_Flags = LVMAF_HEADERDRAWTOEND;
2209 * Seems to be not needed because it's done in MUIM_Setup. No rendering happens before it.
2210 * Height calculation moved to MUIM_Setup because font pointer can be NULL here (if user-specified
2211 * font failed to open). In this case we fail back to the font specified in MUI's AreaData, but
2212 * it becomes known only in MUIM_Setup
2214 CalcHeight(data->icld_LVMAttribs, data->icld_IconLabelFont); */
2217 /* Get/Set initial values */
2218 /* TODO: TrimVolumeNames should be prefs settable */
2219 data->icld__Option_TrimVolumeNames = TRUE;
2220 /* TODO: Adjust overlap by window border width */
2221 data->icld__Option_IconBorderOverlap = 10;
2223 data->icld__Option_IconListMode = (UBYTE)GetTagData(MUIA_IconList_IconListMode, 0, message->ops_AttrList);
2224 data->icld__Option_LabelTextMode = (UBYTE)GetTagData(MUIA_IconList_LabelText_Mode, 0, message->ops_AttrList);
2225 data->icld__Option_LabelTextMaxLen = (ULONG)GetTagData(MUIA_IconList_LabelText_MaxLineLen, ILC_ICONLABEL_MAXLINELEN_DEFAULT, message->ops_AttrList);
2226 data->icld__Option_DragImageTransparent = (BOOL)GetTagData(MUIA_IconList_DragImageTransparent, FALSE, message->ops_AttrList);
2228 if ( data->icld__Option_LabelTextMaxLen < ILC_ICONLABEL_SHORTEST )
2229 data->icld__Option_LabelTextMaxLen = ILC_ICONLABEL_MAXLINELEN_DEFAULT;
2231 data->icld__Option_LastLabelTextMaxLen = data->icld__Option_LabelTextMaxLen;
2233 #if defined(DEBUG_ILC_FUNCS)
2234 D(bug("[IconList] %s: MaxLineLen : %ld\n", __PRETTY_FUNCTION__, data->icld__Option_LabelTextMaxLen));
2235 #endif
2236 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_NEWSIZE;
2237 data->ehn.ehn_Priority = 0;
2238 data->ehn.ehn_Flags = 0;
2239 data->ehn.ehn_Object = obj;
2240 data->ehn.ehn_Class = CLASS;
2242 data->icld_SortFlags = MUIV_IconList_Sort_ByName;
2243 data->icld_DisplayFlags = ICONLIST_DISP_SHOWINFO;
2245 __iconlist_UpdateLabels_hook.h_Entry = (HOOKFUNC)IconList__HookFunc_UpdateLabelsFunc;
2247 DoMethod
2249 obj, MUIM_Notify, MUIA_IconList_LabelText_MaxLineLen, MUIV_EveryTime,
2250 (IPTR)obj, 3,
2251 MUIM_CallHook, &__iconlist_UpdateLabels_hook, (IPTR)CLASS
2254 DoMethod
2256 obj, MUIM_Notify, MUIA_IconList_LabelText_MultiLine, MUIV_EveryTime,
2257 (IPTR)obj, 3,
2258 MUIM_CallHook, &__iconlist_UpdateLabels_hook, (IPTR)CLASS
2261 #if defined(DEBUG_ILC_FUNCS)
2262 D(bug("[IconList] obj = %ld\n", obj));
2263 #endif
2264 return (IPTR)obj;
2268 ///OM_DISPOSE()
2269 /**************************************************************************
2270 OM_DISPOSE
2271 **************************************************************************/
2272 IPTR IconList__OM_DISPOSE(struct IClass *CLASS, Object *obj, Msg message)
2274 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2275 struct IconEntry *node = NULL;
2277 #if defined(DEBUG_ILC_FUNCS)
2278 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2279 #endif
2281 #if defined(__AROS__)
2282 ForeachNode(&data->icld_IconList, node)
2283 #else
2284 Foreach_Node(&data->icld_IconList, node);
2285 #endif
2287 if (node->ie_DiskObj)
2288 FreeDiskObject(node->ie_DiskObj);
2291 if (data->icld_Pool) DeletePool(data->icld_Pool);
2293 DoSuperMethodA(CLASS,obj,message);
2294 return (IPTR)NULL;
2298 ///OM_SET()
2299 /**************************************************************************
2300 OM_SET
2301 **************************************************************************/
2302 IPTR IconList__OM_SET(struct IClass *CLASS, Object *obj, struct opSet *message)
2304 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2305 struct TagItem *tag = NULL,
2306 *tags = NULL;
2308 WORD oldleft = data->icld_ViewX,
2309 oldtop = data->icld_ViewY;
2310 //oldwidth = data->icld_ViewWidth,
2311 //oldheight = data->icld_ViewHeight;
2313 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ATTRIBS)
2314 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2315 #endif
2317 /* parse initial taglist */
2318 for (tags = message->ops_AttrList; (tag = NextTagItem((TAGITEM)&tags)); )
2320 switch (tag->ti_Tag)
2322 case MUIA_Virtgroup_Left:
2323 #if defined(DEBUG_ILC_ATTRIBS)
2324 D(bug("[IconList] %s: MUIA_Virtgroup_Left %ld\n", __PRETTY_FUNCTION__, tag->ti_Data));
2325 #endif
2326 if (data->icld_ViewX != tag->ti_Data)
2327 data->icld_ViewX = tag->ti_Data;
2328 break;
2330 case MUIA_Virtgroup_Top:
2331 #if defined(DEBUG_ILC_ATTRIBS)
2332 D(bug("[IconList] %s: MUIA_Virtgroup_Top %ld\n", __PRETTY_FUNCTION__, tag->ti_Data));
2333 #endif
2334 if (data->icld_ViewY != tag->ti_Data)
2335 data->icld_ViewY = tag->ti_Data;
2336 break;
2338 case MUIA_IconList_Rastport:
2339 #if defined(DEBUG_ILC_ATTRIBS)
2340 D(bug("[IconList] %s: MUIA_IconList_Rastport 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2341 #endif
2342 data->icld_DisplayRastPort = (struct RastPort*)tag->ti_Data;
2343 data->icld_DrawOffsetX = _mleft(obj);
2344 data->icld_DrawOffsetY = _mtop(obj);
2345 if (data->icld_BufferRastPort != NULL)
2347 //Buffer still set!?!?!
2349 SET(obj, MUIA_IconList_BufferRastport, tag->ti_Data);
2350 break;
2352 case MUIA_IconList_BufferRastport:
2353 #if defined(DEBUG_ILC_ATTRIBS)
2354 D(bug("[IconList] %s: MUIA_IconList_BufferRastport 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2355 #endif
2356 data->icld_BufferRastPort = (struct RastPort*)tag->ti_Data;
2357 break;
2359 case MUIA_Font:
2360 #if defined(DEBUG_ILC_ATTRIBS)
2361 D(bug("[IconList] %s: MUIA_Font 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2362 #endif
2363 data->icld_IconLabelFont = (struct TextFont*)tag->ti_Data;
2364 /* FIXME: Should we call CalcHeight() here because our font changed? */
2365 break;
2367 case MUIA_IconList_LabelInfoText_Font:
2368 #if defined(DEBUG_ILC_ATTRIBS)
2369 D(bug("[IconList] %s: MUIA_IconList_LabelInfoText_Font 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2370 #endif
2371 data->icld_IconInfoFont = (struct TextFont*)tag->ti_Data;
2372 break;
2374 case MUIA_IconList_DisplayFlags:
2376 #if defined(DEBUG_ILC_ATTRIBS)
2377 D(bug("[IconList] %s: MUIA_IconList_DisplayFlags %08x\n", __PRETTY_FUNCTION__, tag->ti_Data));
2378 #endif
2379 // ULONG origModeFlags = data->icld_DisplayFlags & (ICONLIST_DISP_MODEDEFAULT|ICONLIST_DISP_MODELABELRIGHT|ICONLIST_DISP_MODELIST);
2380 data->icld_DisplayFlags = (ULONG)tag->ti_Data;
2382 if (data->icld_DisplayFlags & ICONLIST_DISP_BUFFERED)
2384 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2385 D(bug("[IconList] %s: MUIA_IconList_DisplayFlags & ICONLIST_DISP_BUFFERED\n", __PRETTY_FUNCTION__));
2386 #endif
2387 if ((data->icld_BufferRastPort != NULL)
2388 && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
2390 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2391 D(bug("[IconList] %s: BackLayer @ %p for BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
2392 #endif
2393 if ((GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_WIDTH) != data->icld_ViewWidth)
2394 || (GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_HEIGHT) != data->icld_ViewHeight))
2396 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
2397 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2398 D(bug("[IconList] %s: Destroying old BackLayer\n", __PRETTY_FUNCTION__));
2399 #endif
2400 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2401 DeleteLayer(0, oldLayer);
2405 if ((data->icld_BufferRastPort == NULL) || (data->icld_BufferRastPort == data->icld_DisplayRastPort))
2407 struct BitMap *bitmap_New = NULL;
2408 ULONG tmp_RastDepth;
2409 struct Layer_Info *li = NULL;
2411 tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
2412 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
2413 data->icld_ViewHeight,
2414 tmp_RastDepth,
2415 BMF_CLEAR,
2416 data->icld_DisplayRastPort->BitMap))!=NULL)
2418 if ((data->icld_BufferRastPort = CreateRastPort())!=NULL)
2420 data->icld_BufferRastPort->BitMap = bitmap_New;
2421 if ((li = NewLayerInfo()))
2423 if ((data->icld_BufferRastPort->Layer = CreateUpfrontLayer(li, data->icld_BufferRastPort->BitMap, 0, 0, data->icld_ViewWidth - 1, data->icld_ViewHeight - 1, 0, NULL)))
2426 * Mark it as a buffered rastport.
2429 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2430 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
2431 #endif
2432 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
2433 data->icld_DrawOffsetX = 0;
2434 data->icld_DrawOffsetY = 0;
2436 else
2437 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2439 else
2440 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2442 else
2443 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2445 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
2447 if (bitmap_New) FreeBitMap(bitmap_New);
2448 if (li) DisposeLayerInfo(li);
2449 data->icld_DrawOffsetX = _mleft(obj);
2450 data->icld_DrawOffsetY = _mtop(obj);
2454 else
2456 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
2458 //Free up the buffers layer, rastport and bitmap since they are no longer needed ..
2459 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
2460 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2461 InstallClipRegion(oldLayer, NULL);
2462 DeleteLayer(0, oldLayer);
2463 FreeBitMap(data->icld_BufferRastPort->BitMap);
2464 data->icld_DrawOffsetX = _mleft(obj);
2465 data->icld_DrawOffsetY = _mtop(obj);
2468 SET(obj, MUIA_IconList_Changed, TRUE);
2470 break;
2472 case MUIA_IconList_SortFlags:
2473 #if defined(DEBUG_ILC_ATTRIBS)
2474 D(bug("[IconList] %s: MUIA_IconList_SortFlags %08x\n", __PRETTY_FUNCTION__, tag->ti_Data));
2475 #endif
2476 data->icld_SortFlags = (ULONG)tag->ti_Data;
2477 break;
2479 case MUIA_IconList_DragImageTransparent:
2480 data->icld__Option_DragImageTransparent = (BOOL)tag->ti_Data;
2481 break;
2483 case MUIA_IconList_IconListMode:
2484 #if defined(DEBUG_ILC_ATTRIBS)
2485 D(bug("[IconList] %s: MUIA_IconList_IconListMode %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2486 #endif
2487 data->icld__Option_IconListMode = (UBYTE)tag->ti_Data;
2488 break;
2490 case MUIA_IconList_LabelText_Mode:
2491 #if defined(DEBUG_ILC_ATTRIBS)
2492 D(bug("[IconList] %s: MUIA_IconList_LabelText_Mode %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2493 #endif
2494 data->icld__Option_LabelTextMode = (UBYTE)tag->ti_Data;
2495 break;
2497 case MUIA_IconList_LabelText_MaxLineLen:
2498 #if defined(DEBUG_ILC_ATTRIBS)
2499 D(bug("[IconList] %s: MUIA_IconList_LabelText_MaxLineLen %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2500 #endif
2501 if (tag->ti_Data >= ILC_ICONLABEL_SHORTEST)
2503 data->icld__Option_LabelTextMaxLen = (ULONG)tag->ti_Data;
2505 else
2507 data->icld__Option_LabelTextMaxLen = ILC_ICONLABEL_MAXLINELEN_DEFAULT;
2509 break;
2511 case MUIA_IconList_LabelText_MultiLine:
2512 #if defined(DEBUG_ILC_ATTRIBS)
2513 D(bug("[IconList] %s: MUIA_IconList_LabelText_MultiLine %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2514 #endif
2515 data->icld__Option_LabelTextMultiLine = (ULONG)tag->ti_Data;
2516 if (data->icld__Option_LabelTextMultiLine == 0)data->icld__Option_LabelTextMultiLine = 1;
2517 break;
2519 case MUIA_IconList_LabelText_MultiLineOnFocus:
2520 #if defined(DEBUG_ILC_ATTRIBS)
2521 D(bug("[IconList] %s: MUIA_IconList_LabelText_MultiLineOnFocus %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2522 #endif
2523 data->icld__Option_LabelTextMultiLineOnFocus = (BOOL)tag->ti_Data;
2524 break;
2526 case MUIA_IconList_Icon_HorizontalSpacing:
2527 #if defined(DEBUG_ILC_ATTRIBS)
2528 D(bug("[IconList] %s: MUIA_IconList_Icon_HorizontalSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2529 #endif
2530 data->icld__Option_IconHorizontalSpacing = (UBYTE)tag->ti_Data;
2531 break;
2533 case MUIA_IconList_Icon_VerticalSpacing:
2534 #if defined(DEBUG_ILC_ATTRIBS)
2535 D(bug("[IconList] %s: MUIA_IconList_Icon_VerticalSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2536 #endif
2537 data->icld__Option_IconVerticalSpacing = (UBYTE)tag->ti_Data;
2538 break;
2540 case MUIA_IconList_Icon_ImageSpacing:
2541 #if defined(DEBUG_ILC_ATTRIBS)
2542 D(bug("[IconList] %s: MUIA_IconList_Icon_ImageSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2543 #endif
2544 data->icld__Option_IconImageSpacing = (UBYTE)tag->ti_Data;
2545 break;
2547 case MUIA_IconList_LabelText_HorizontalPadding:
2548 #if defined(DEBUG_ILC_ATTRIBS)
2549 D(bug("[IconList] %s: MUIA_IconList_LabelText_HorizontalPadding %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2550 #endif
2551 data->icld__Option_LabelTextHorizontalPadding = (UBYTE)tag->ti_Data;
2552 break;
2554 case MUIA_IconList_LabelText_VerticalPadding:
2555 #if defined(DEBUG_ILC_ATTRIBS)
2556 D(bug("[IconList] %s: MUIA_IconList_LabelText_VerticalPadding %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2557 #endif
2558 data->icld__Option_LabelTextVerticalPadding = (UBYTE)tag->ti_Data;
2559 break;
2561 case MUIA_IconList_LabelText_BorderWidth:
2562 #if defined(DEBUG_ILC_ATTRIBS)
2563 D(bug("[IconList] %s: MUIA_IconList_LabelText_BorderWidth %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2564 #endif
2565 data->icld__Option_LabelTextBorderWidth = (UBYTE)tag->ti_Data;
2566 break;
2568 case MUIA_IconList_LabelText_BorderHeight:
2569 #if defined(DEBUG_ILC_ATTRIBS)
2570 D(bug("[IconList] %s: MUIA_IconList_LabelText_BorderHeight %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2571 #endif
2572 data->icld__Option_LabelTextBorderHeight = (UBYTE)tag->ti_Data;
2573 break;
2575 case MUIA_IconList_LabelText_Pen:
2576 data->icld_LabelPen = (ULONG)tag->ti_Data;
2577 break;
2579 case MUIA_IconList_LabelText_ShadowPen:
2580 data->icld_LabelShadowPen = (ULONG)tag->ti_Data;
2581 break;
2583 case MUIA_IconList_LabelInfoText_Pen:
2584 data->icld_InfoPen = (ULONG)tag->ti_Data;
2585 break;
2587 case MUIA_IconList_LabelInfoText_ShadowPen:
2588 data->icld_InfoShadowPen = (ULONG)tag->ti_Data;
2589 break;
2591 /* Settings defined by the view class */
2592 case MUIA_IconListview_FixedBackground:
2593 #if defined(DEBUG_ILC_ATTRIBS)
2594 D(bug("[IconList] %s: MUIA_IconListview_FixedBackground\n", __PRETTY_FUNCTION__));
2595 #endif
2596 data->icld__Option_IconListFixedBackground = (BOOL)tag->ti_Data;
2597 break;
2599 case MUIA_IconListview_ScaledBackground:
2600 #if defined(DEBUG_ILC_ATTRIBS)
2601 D(bug("[IconList] %s: MUIA_IconListview_ScaledBackground\n", __PRETTY_FUNCTION__));
2602 #endif
2603 data->icld__Option_IconListScaledBackground = (BOOL)tag->ti_Data;
2604 break;
2606 /* We listen for MUIA_Background and set default values for known types */
2607 case MUIA_Background:
2608 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2609 D(bug("[IconList] %s: MUIA_Background\n", __PRETTY_FUNCTION__));
2610 #endif
2612 char *bgmode_string = (char *)tag->ti_Data;
2613 BYTE this_mode = bgmode_string[0] - 48;
2615 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2616 D(bug("[IconList] %s: MUIA_Background | MUI BG Mode = %d\n", __PRETTY_FUNCTION__, this_mode));
2617 #endif
2618 switch (this_mode)
2620 case 0:
2621 //MUI Pattern
2622 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2623 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2624 break;
2625 case 2:
2626 //MUI RGB color
2627 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2628 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2629 break;
2630 case 7:
2631 //Zune Gradient
2632 NNSET(obj, MUIA_IconListview_FixedBackground, TRUE);
2633 NNSET(obj, MUIA_IconListview_ScaledBackground, TRUE);
2634 break;
2635 case 5:
2636 //Image
2637 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2638 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2639 break;
2642 break;
2643 case MUIA_IconList_IconsDropped:
2644 data->icld_DragDropEvent = (struct IconList_Drop_Event *)tag->ti_Data;
2645 break;
2649 #if defined(DEBUG_ILC_ATTRIBS)
2650 D(bug("[IconList] %s(), out of switch\n", __PRETTY_FUNCTION__));
2651 #endif
2652 if ((oldleft != data->icld_ViewX) || (oldtop != data->icld_ViewY))
2654 data->icld_UpdateMode = UPDATE_SCROLL;
2655 data->update_scrolldx = data->icld_ViewX - oldleft;
2656 data->update_scrolldy = data->icld_ViewY - oldtop;
2657 #if defined(DEBUG_ILC_ATTRIBS)
2658 D(bug("[IconList] %s(), call MUI_Redraw()\n", __PRETTY_FUNCTION__));
2659 #endif
2660 MUI_Redraw(obj, MADF_DRAWUPDATE);
2663 #if defined(DEBUG_ILC_ATTRIBS)
2664 D(bug("[IconList] %s(), call DoSuperMethodA()\n", __PRETTY_FUNCTION__));
2665 #endif
2666 return DoSuperMethodA(CLASS, obj, (Msg)message);
2670 ///OM_GET()
2671 /**************************************************************************
2672 OM_GET
2673 **************************************************************************/
2674 IPTR IconList__OM_GET(struct IClass *CLASS, Object *obj, struct opGet *message)
2676 /* small macro to simplify return value storage */
2677 #define STORE *(message->opg_Storage)
2678 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2680 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ATTRIBS)
2681 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2682 #endif
2684 switch (message->opg_AttrID)
2686 case MUIA_IconList_Rastport: STORE = (IPTR)data->icld_DisplayRastPort; return 1;
2687 case MUIA_IconList_BufferRastport: STORE = (IPTR)data->icld_BufferRastPort; return 1;
2688 case MUIA_IconList_BufferLeft: STORE = (IPTR)data->icld_DrawOffsetX; return 1;
2689 case MUIA_IconList_BufferTop: STORE = (IPTR)data->icld_DrawOffsetY; return 1;
2690 case MUIA_IconList_BufferWidth:
2691 case MUIA_IconList_Width: STORE = (IPTR)data->icld_AreaWidth; return 1;
2692 case MUIA_IconList_BufferHeight:
2693 case MUIA_IconList_Height: STORE = (IPTR)data->icld_AreaHeight; return 1;
2694 case MUIA_IconList_IconsDropped: STORE = (IPTR)data->icld_DragDropEvent; return 1;
2695 case MUIA_IconList_Clicked: STORE = (IPTR)&data->icld_ClickEvent; return 1;
2696 case MUIA_IconList_IconListMode: STORE = (IPTR)data->icld__Option_IconListMode; return 1;
2697 case MUIA_IconList_LabelText_Mode: STORE = (IPTR)data->icld__Option_LabelTextMode; return 1;
2698 case MUIA_IconList_LabelText_MaxLineLen: STORE = (IPTR)data->icld__Option_LabelTextMaxLen; return 1;
2699 case MUIA_IconList_LabelText_MultiLine: STORE = (IPTR)data->icld__Option_LabelTextMultiLine; return 1;
2700 case MUIA_IconList_LabelText_MultiLineOnFocus: STORE = (IPTR)data->icld__Option_LabelTextMultiLineOnFocus; return 1;
2701 case MUIA_IconList_DisplayFlags: STORE = (IPTR)data->icld_DisplayFlags; return 1;
2702 case MUIA_IconList_SortFlags: STORE = (IPTR)data->icld_SortFlags; return 1;
2704 case MUIA_IconList_FocusIcon: STORE = (IPTR)data->icld_FocusIcon; return 1;
2706 case MUIA_Font: STORE = (IPTR)data->icld_IconLabelFont; return 1;
2707 case MUIA_IconList_LabelText_Pen: STORE = (IPTR)data->icld_LabelPen; return 1;
2708 case MUIA_IconList_LabelText_ShadowPen: STORE = (IPTR)data->icld_LabelShadowPen; return 1;
2709 case MUIA_IconList_LabelInfoText_Font: STORE = (IPTR)data->icld_IconInfoFont; return 1;
2710 case MUIA_IconList_LabelInfoText_Pen: STORE = (IPTR)data->icld_InfoPen; return 1;
2711 case MUIA_IconList_LabelInfoText_ShadowPen: STORE = (IPTR)data->icld_InfoShadowPen; return 1;
2712 case MUIA_IconList_DragImageTransparent: STORE = (IPTR)data->icld__Option_DragImageTransparent; return 1;
2714 case MUIA_IconList_Icon_HorizontalSpacing: STORE = (IPTR)data->icld__Option_IconHorizontalSpacing; return 1;
2715 case MUIA_IconList_Icon_VerticalSpacing: STORE = (IPTR)data->icld__Option_IconVerticalSpacing; return 1;
2716 case MUIA_IconList_Icon_ImageSpacing: STORE = (IPTR)data->icld__Option_IconImageSpacing; return 1;
2717 case MUIA_IconList_LabelText_HorizontalPadding: STORE = (IPTR)data->icld__Option_LabelTextHorizontalPadding; return 1;
2718 case MUIA_IconList_LabelText_VerticalPadding: STORE = (IPTR)data->icld__Option_LabelTextVerticalPadding; return 1;
2719 case MUIA_IconList_LabelText_BorderWidth: STORE = (IPTR)data->icld__Option_LabelTextBorderWidth; return 1;
2720 case MUIA_IconList_LabelText_BorderHeight: STORE = (IPTR)data->icld__Option_LabelTextBorderHeight; return 1;
2722 /* Settings defined by the view class */
2723 case MUIA_IconListview_FixedBackground: STORE = (IPTR)data->icld__Option_IconListFixedBackground; return 1;
2724 case MUIA_IconListview_ScaledBackground: STORE = (IPTR)data->icld__Option_IconListScaledBackground; return 1;
2726 /* ICON obj Changes */
2727 case MUIA_Virtgroup_Left: STORE = (IPTR)data->icld_ViewX; return 1;
2728 case MUIA_Virtgroup_Top: STORE = (IPTR)data->icld_ViewY; return 1;
2729 case MUIA_Family_List: STORE = (IPTR)&(data->icld_IconList); return 1; /* Get our list object */
2731 /* TODO: Get the version/revision from our config.. */
2732 case MUIA_Version: STORE = (IPTR)1; return 1;
2733 case MUIA_Revision: STORE = (IPTR)7; return 1;
2736 return DoSuperMethodA(CLASS, obj, (Msg) message);
2737 #undef STORE
2741 IPTR IconList__MUIM_Family_AddHead(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddHead *message)
2743 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2744 #if defined(DEBUG_ILC_FUNCS)
2745 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2746 #endif
2748 if (message->obj)
2750 /* TODO: Use the correct _OBJECT() code when we switch to icon.mui */
2751 // AddHead(&(data->icld_IconList), (struct Node *)_OBJECT(message->obj));
2752 AddHead(&(data->icld_IconList), (struct Node *)message->obj);
2753 return TRUE;
2755 else
2756 return FALSE;
2759 IPTR IconList__MUIM_Family_AddTail(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddTail *message)
2761 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2762 #if defined(DEBUG_ILC_FUNCS)
2763 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2764 #endif
2766 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));
2768 if (message->obj)
2770 /* TODO: Use the correct _OBJECT() code when we switch to icon.mui */
2771 // AddTail(&(data->icld_IconList), (struct Node *)_OBJECT(message->obj));
2772 AddTail(&(data->icld_IconList), (struct Node *)message->obj);
2773 return TRUE;
2775 else
2776 return FALSE;
2778 return (IPTR)NULL;
2780 #if !defined(WANDERER_BUILTIN_ICONLIST)
2781 IPTR IconList__OM_ADDMEMBER(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddTail *message)
2783 return IconList__MUIM_Family_AddTail(CLASS, obj, message);
2785 #endif
2787 IPTR IconList__MUIM_Family_Remove(struct IClass *CLASS, Object *obj, struct MUIP_Family_Remove *message)
2789 // struct IconList_DATA *data = INST_DATA(CLASS, obj);
2790 #if defined(DEBUG_ILC_FUNCS)
2791 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2792 #endif
2794 D(bug("[IconList] %s: entry @ 0x%p '%s'\n", __PRETTY_FUNCTION__, message->obj, ((struct IconEntry *)message->obj)->ie_IconNode.ln_Name));
2796 if (message->obj)
2798 /* TODO: Use the correct _OBJECT() code when we switch to icon.mui */
2799 // Remove((struct Node *)_OBJECT(message->obj));
2800 Remove((struct Node *)message->obj);
2801 return TRUE;
2803 else
2804 return FALSE;
2806 return (IPTR)NULL;
2808 #if !defined(WANDERER_BUILTIN_ICONLIST)
2809 IPTR IconList__OM_REMMEMBER(struct IClass *CLASS, Object *obj, struct MUIP_Family_Remove *message)
2811 return IconList__MUIM_Family_Remove(CLASS, obj, message);
2813 #endif
2815 ///MUIM_Setup()
2816 /**************************************************************************
2817 MUIM_Setup
2818 **************************************************************************/
2819 IPTR IconList__MUIM_Setup(struct IClass *CLASS, Object *obj, struct MUIP_Setup *message)
2821 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2822 struct IconEntry *node = NULL;
2823 IPTR geticon_error = 0, iconlistScreen;
2825 #if defined(DEBUG_ILC_FUNCS)
2826 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2827 #endif
2829 if (!DoSuperMethodA(CLASS, obj, (Msg) message)) return (IPTR)NULL;
2831 iconlistScreen = (IPTR)_screen(obj);
2832 #if defined(DEBUG_ILC_ICONRENDERING)
2833 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
2834 #endif
2836 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
2838 /* Get Internal Objects to use if not set .. */
2839 data->icld_DisplayRastPort = NULL;
2840 data->icld_BufferRastPort = NULL;
2842 if (data->icld_IconLabelFont == NULL) data->icld_IconLabelFont = _font(obj);
2843 if (data->icld_IconInfoFont == NULL) data->icld_IconInfoFont = data->icld_IconLabelFont;
2846 * Here we have our font, either from user preferences or from MUI's AreaData.
2847 * It's right time to set up some sizes.
2849 if (data->icld_LVMAttribs)
2850 CalcHeight(data->icld_LVMAttribs, data->icld_IconLabelFont);
2851 #if defined(DEBUG_ILC_ICONRENDERING)
2852 D(bug("[IconList] %s: Use Font @ 0x%p, RastPort @ 0x%p\n", __PRETTY_FUNCTION__, data->icld_IconLabelFont, data->icld_BufferRastPort ));
2853 #endif
2855 /* Set our base options .. */
2856 data->icld_LabelPen = _pens(obj)[MPEN_SHINE];
2857 data->icld_LabelShadowPen = _pens(obj)[MPEN_SHADOW];
2858 data->icld_InfoPen = _pens(obj)[MPEN_SHINE];
2859 data->icld_InfoShadowPen = _pens(obj)[MPEN_SHADOW];
2861 data->icld__Option_LabelTextMultiLine = 1;
2862 data->icld__Option_LastLabelTextMultiLine = data->icld__Option_LabelTextMultiLine;
2864 data->icld__Option_LabelTextMultiLineOnFocus = FALSE;
2866 data->icld__Option_IconHorizontalSpacing = ILC_ICON_HORIZONTALMARGIN_DEFAULT;
2867 data->icld__Option_IconVerticalSpacing = ILC_ICON_VERTICALMARGIN_DEFAULT;
2868 data->icld__Option_IconImageSpacing = ILC_ICONLABEL_IMAGEMARGIN_DEFAULT;
2869 data->icld__Option_LabelTextHorizontalPadding = ILC_ICONLABEL_HORIZONTALTEXTMARGIN_DEFAULT;
2870 data->icld__Option_LabelTextVerticalPadding = ILC_ICONLABEL_VERTICALTEXTMARGIN_DEFAULT;
2871 data->icld__Option_LabelTextBorderWidth = ILC_ICONLABEL_BORDERWIDTH_DEFAULT;
2872 data->icld__Option_LabelTextBorderHeight = ILC_ICONLABEL_BORDERHEIGHT_DEFAULT;
2874 if (data->icld_LVMAttribs)
2876 data->icld_LVMAttribs->lvma_IconDrawer = GetIconTags
2878 "WANDERER:Icons/drawer",
2879 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
2880 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
2881 ICONGETA_FailIfUnavailable, TRUE,
2882 ICONGETA_GenerateImageMasks, TRUE,
2883 ICONA_ErrorCode, &geticon_error,
2884 TAG_DONE
2887 #if defined(DEBUG_ILC_ICONRENDERING)
2888 if (data->icld_LVMAttribs->lvma_IconDrawer == NULL)
2890 D(bug("[IconList] %s: Couldnt get drawer DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
2892 #endif
2893 data->icld_LVMAttribs->lvma_IconFile = GetIconTags
2895 "WANDERER:Icons/file",
2896 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
2897 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
2898 ICONGETA_FailIfUnavailable, TRUE,
2899 ICONGETA_GenerateImageMasks, TRUE,
2900 ICONA_ErrorCode, &geticon_error,
2901 TAG_DONE
2904 #if defined(DEBUG_ILC_ICONRENDERING)
2905 if (data->icld_LVMAttribs->lvma_IconFile == NULL)
2907 D(bug("[IconList] %s: Couldnt get file DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
2909 #endif
2912 #if defined(__AROS__)
2913 ForeachNode(&data->icld_IconList, node)
2914 #else
2915 Foreach_Node(&data->icld_IconList, node);
2916 #endif
2918 if (!node->ie_DiskObj)
2920 if (!(node->ie_DiskObj = GetIconTags(node->ie_IconNode.ln_Name,
2921 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
2922 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
2923 ICONGETA_GenerateImageMasks, TRUE,
2924 ICONGETA_FailIfUnavailable, FALSE,
2925 ICONA_ErrorCode, &geticon_error,
2926 TAG_DONE)))
2928 #if defined(DEBUG_ILC_ICONRENDERING)
2929 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));
2930 #endif
2931 /* We should probably remove this node if the entry cant be obtained ? */
2935 return 1;
2939 ///MUIM_Show()
2940 /**************************************************************************
2941 MUIM_Show
2942 **************************************************************************/
2943 IPTR IconList__MUIM_Show(struct IClass *CLASS, Object *obj, struct MUIP_Show *message)
2945 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2946 LONG newleft,
2947 newtop;
2948 IPTR rc;
2950 #if defined(DEBUG_ILC_FUNCS)
2951 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2952 #endif
2954 if ((rc = DoSuperMethodA(CLASS, obj, (Msg)message)))
2956 newleft = data->icld_ViewX;
2957 newtop = data->icld_ViewY;
2959 if (newleft + _mwidth(obj) > data->icld_AreaWidth)
2960 newleft = data->icld_AreaWidth - _mwidth(obj);
2961 if (newleft < 0)
2962 newleft = 0;
2964 if (newtop + _mheight(obj) > data->icld_AreaHeight)
2965 newtop = data->icld_AreaHeight - _mheight(obj);
2966 if (newtop < 0)
2967 newtop = 0;
2969 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
2971 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
2972 MUIA_Virtgroup_Top, newtop,
2973 TAG_DONE);
2976 /* Get Internal Objects to use if not set .. */
2977 if (data->icld_DisplayRastPort == NULL)
2979 if (_rp(obj) != NULL)
2981 data->icld_DisplayRastPort = CloneRastPort(_rp(obj));
2983 #if defined(DEBUG_ILC_ICONRENDERING)
2984 else
2986 D(bug("[IconList] IconList__MUIM_Show: ERROR - NULL RastPort!\n"));
2988 #endif
2991 if (data->icld_DisplayFlags & ICONLIST_DISP_BUFFERED)
2993 struct BitMap *bitmap_New = NULL;
2994 struct Layer_Info *li = NULL;
2996 ULONG tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
2997 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
2998 data->icld_ViewHeight,
2999 tmp_RastDepth,
3000 BMF_CLEAR,
3001 data->icld_DisplayRastPort->BitMap))!=NULL)
3003 if ((data->icld_BufferRastPort = CreateRastPort())!=NULL)
3005 data->icld_BufferRastPort->BitMap = bitmap_New;
3006 if ((li = NewLayerInfo()))
3008 if ((data->icld_BufferRastPort->Layer = CreateUpfrontLayer(li, data->icld_BufferRastPort->BitMap, 0, 0, data->icld_ViewWidth - 1, data->icld_ViewHeight - 1, 0, NULL)))
3011 * Mark it as a buffered rastport.
3014 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
3015 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
3016 #endif
3017 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
3018 data->icld_DrawOffsetX = 0;
3019 data->icld_DrawOffsetY = 0;
3021 else
3022 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3024 else
3025 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3027 else
3028 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3030 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
3032 if (bitmap_New) FreeBitMap(bitmap_New);
3033 if (li) DisposeLayerInfo(li);
3034 data->icld_DrawOffsetX = _mleft(obj);
3035 data->icld_DrawOffsetY = _mtop(obj);
3038 else
3040 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3041 data->icld_DrawOffsetX = _mleft(obj);
3042 data->icld_DrawOffsetY = _mtop(obj);
3045 if (data->icld_IconLabelFont == NULL) data->icld_IconLabelFont = _font(obj);
3046 if (data->icld_IconInfoFont == NULL) data->icld_IconInfoFont = data->icld_IconLabelFont;
3047 #if defined(DEBUG_ILC_ICONRENDERING)
3048 D(bug("[IconList] IconList__MUIM_Show: Use Font @ 0x%p, RastPort @ 0x%p\n", data->icld_IconLabelFont, data->icld_BufferRastPort ));
3049 #endif
3051 if ((data->icld_BufferRastPort) && (data->icld_IconLabelFont))
3052 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
3054 return rc;
3058 ///MUIM_Hide()
3059 /**************************************************************************
3060 MUIM_Hide
3061 **************************************************************************/
3062 IPTR IconList__MUIM_Hide(struct IClass *CLASS, Object *obj, struct MUIP_Hide *message)
3064 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3065 IPTR rc;
3067 #if defined(DEBUG_ILC_FUNCS)
3068 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3069 #endif
3071 if ((rc = DoSuperMethodA(CLASS, obj, (Msg)message)))
3073 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
3075 DeleteLayer(0, data->icld_BufferRastPort->Layer);
3078 data->icld_BufferRastPort = NULL;
3080 if (data->icld_DisplayRastPort)
3081 FreeRastPort(data->icld_DisplayRastPort);
3083 data->icld_DisplayRastPort = NULL;
3085 return rc;
3089 ///MUIM_Cleanup()
3090 /**************************************************************************
3091 MUIM_Cleanup
3092 **************************************************************************/
3093 IPTR IconList__MUIM_Cleanup(struct IClass *CLASS, Object *obj, struct MUIP_Cleanup *message)
3095 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3096 struct IconEntry *node = NULL;
3098 #if defined(DEBUG_ILC_FUNCS)
3099 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3100 #endif
3102 #if defined(__AROS__)
3103 ForeachNode(&data->icld_IconList, node)
3104 #else
3105 Foreach_Node(&data->icld_IconList, node);
3106 #endif
3108 if (node->ie_DiskObj)
3110 FreeDiskObject(node->ie_DiskObj);
3111 node->ie_DiskObj = NULL;
3115 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
3117 return DoSuperMethodA(CLASS, obj, (Msg)message);
3121 ///MUIM_AskMinMax()
3122 /**************************************************************************
3123 MUIM_AskMinMax
3124 **************************************************************************/
3125 IPTR IconList__MUIM_AskMinMax(struct IClass *CLASS, Object *obj, struct MUIP_AskMinMax *message)
3127 ULONG rc = DoSuperMethodA(CLASS, obj, (Msg) message);
3129 #if defined(DEBUG_ILC_FUNCS)
3130 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3131 #endif
3133 message->MinMaxInfo->MinWidth += 96;
3134 message->MinMaxInfo->MinHeight += 64;
3136 message->MinMaxInfo->DefWidth += 200;
3137 message->MinMaxInfo->DefHeight += 180;
3139 message->MinMaxInfo->MaxWidth = MUI_MAXMAX;
3140 message->MinMaxInfo->MaxHeight = MUI_MAXMAX;
3142 return rc;
3146 ///MUIM_Layout()
3147 /**************************************************************************
3148 MUIM_Layout
3149 **************************************************************************/
3150 IPTR IconList__MUIM_Layout(struct IClass *CLASS, Object *obj,struct MUIP_Layout *message)
3152 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3153 ULONG rc;
3155 #if defined(DEBUG_ILC_FUNCS)
3156 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3157 #endif
3159 rc = DoSuperMethodA(CLASS, obj, (Msg)message);
3161 data->icld_ViewWidth = _mwidth(obj);
3162 data->icld_ViewHeight = _mheight(obj);
3164 return rc;
3168 static LONG FirstVisibleLine(struct IconList_DATA *data)
3170 return data->icld_ViewY / data->icld_LVMAttribs->lmva_RowHeight;
3173 static LONG NumVisibleLines(struct IconList_DATA *data)
3175 LONG visible = data->icld_ViewHeight + data->icld_LVMAttribs->lmva_RowHeight - 1 +
3176 (data->icld_ViewY % data->icld_LVMAttribs->lmva_RowHeight);
3178 visible /= data->icld_LVMAttribs->lmva_RowHeight;
3180 return visible;
3183 static void RenderListViewModeHeaderField(Object *obj, struct IconList_DATA *data,
3184 struct Rectangle *rect, LONG index, BOOL sel)
3186 IPTR penFill, penText, penDark, penBright;
3187 struct Rectangle rendRect;
3188 STRPTR text;
3189 struct TextExtent te;
3190 ULONG fit;
3192 if (sel == TRUE)
3194 penFill = _pens(obj)[MPEN_HALFSHADOW];
3195 penBright = _pens(obj)[MPEN_SHADOW];
3196 penDark = _pens(obj)[MPEN_HALFSHINE];
3198 else
3200 penFill = _pens(obj)[MPEN_HALFSHINE];
3201 penBright = _pens(obj)[MPEN_SHINE];
3202 penDark = _pens(obj)[MPEN_HALFSHADOW];
3204 penText = _pens(obj)[MPEN_TEXT];
3206 rendRect.MinX = rect->MinX;
3207 rendRect.MaxX = rect->MaxX;
3208 rendRect.MinY = rect->MinY;
3209 rendRect.MaxY = rect->MaxY;
3211 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3213 rendRect.MinX -= _mleft(obj);
3214 rendRect.MaxX -= _mleft(obj);
3215 rendRect.MinY -= _mtop(obj);
3216 rendRect.MaxY -= _mtop(obj);
3219 #if defined(DEBUG_ILC_FUNCS)
3220 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
3221 #endif
3223 if (((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0) && (index < NUM_COLUMNS))
3225 text = data->icld_LVMAttribs->lmva_ColumnTitle[index];
3227 SetAPen(data->icld_BufferRastPort, penFill); /* Background */
3228 RectFill(data->icld_BufferRastPort, rendRect.MinX + 1, rendRect.MinY + 1,
3229 rendRect.MaxX - 1, rendRect.MaxY - 1);
3231 SetAPen(data->icld_BufferRastPort, penBright); /* Top/Left */
3232 RectFill(data->icld_BufferRastPort, rendRect.MinX, rendRect.MinY, rendRect.MinX, rendRect.MaxY);
3233 RectFill(data->icld_BufferRastPort, rendRect.MinX + 1, rendRect.MinY, rendRect.MaxX - 1, rendRect.MinY);
3235 SetAPen(data->icld_BufferRastPort,penDark); /* Bottom/Right */
3236 RectFill(data->icld_BufferRastPort, rendRect.MaxX, rendRect.MinY, rendRect.MaxX, rendRect.MaxY);
3237 RectFill(data->icld_BufferRastPort, rendRect.MinX + 1, rendRect.MaxY, rendRect.MaxX - 1, rendRect.MaxY);
3239 /* Draw the Sort indicator .. */
3240 if (index == data->icld_LVMAttribs->lmva_SortColumn)
3242 LONG x = rendRect.MaxX - 4 - 6;
3243 LONG y = (rendRect.MinY + rendRect.MaxY + 1) / 2 - 3;
3245 if (x > rendRect.MinX)
3247 SetAPen(data->icld_BufferRastPort, _pens(obj)[sel ? MPEN_SHADOW : MPEN_HALFSHADOW]);
3248 if (data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
3250 RectFill(data->icld_BufferRastPort, x, y, x + 5, y + 1);
3251 RectFill(data->icld_BufferRastPort, x + 1, y + 2, x + 4, y + 3);
3252 RectFill(data->icld_BufferRastPort, x + 2, y + 4, x + 3, y + 5);
3254 else
3256 RectFill(data->icld_BufferRastPort, x, y + 4, x + 5, y + 5);
3257 RectFill(data->icld_BufferRastPort, x + 1, y + 2, x + 4, y + 3);
3258 RectFill(data->icld_BufferRastPort, x + 2, y, x + 3, y + 1);
3263 rendRect.MinX += HEADERENTRY_SPACING_LEFT;
3264 rendRect.MinY += HEADERLINE_SPACING_TOP;
3265 rendRect.MaxX -= HEADERENTRY_SPACING_RIGHT;
3266 rendRect.MaxY -= HEADERLINE_SPACING_BOTTOM;
3268 if (text && text[0])
3271 fit = TextFit(data->icld_BufferRastPort, text, strlen(text), &te, NULL, 1,
3272 rendRect.MaxX - rendRect.MinX + 1,
3273 rendRect.MaxY - rendRect.MinY + 1);
3275 if (!fit) return;
3277 SetABPenDrMd(data->icld_BufferRastPort, penText, 0, JAM1);
3278 Move(data->icld_BufferRastPort, rendRect.MinX, rendRect.MinY + data->icld_BufferRastPort->TxBaseline);
3279 Text(data->icld_BufferRastPort, text, fit);
3284 static void RenderListViewModeHeader(Object *obj, struct IconList_DATA *data)
3286 struct Rectangle linerect;
3287 LONG x, i;
3288 LONG firstvis, lastvis;
3290 #if defined(DEBUG_ILC_FUNCS)
3291 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
3292 #endif
3294 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
3296 linerect.MinX = _mleft(obj) - data->icld_ViewX;
3297 linerect.MaxX = _mright(obj);
3298 linerect.MinY = _mtop(obj);
3299 linerect.MaxY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight - 1;
3301 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
3303 x = linerect.MinX + HEADERLINE_SPACING_LEFT;
3305 firstvis = FirstVisibleColumnNumber(data);
3306 lastvis = LastVisibleColumnNumber(data);
3308 for(i = 0; i < NUM_COLUMNS; i++)
3310 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
3312 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
3314 BOOL outside = FALSE;
3315 struct Rectangle field_rect;
3317 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
3318 field_rect.MinY = linerect.MinY;
3319 field_rect.MaxX = x + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1 + ((i == lastvis) ? HEADERLINE_SPACING_RIGHT : 0);
3320 field_rect.MaxY = linerect.MaxY;
3322 /* data->update_rect1 and data->update_rect2 may
3323 point to rectangles to indicate that only icons
3324 in any of this rectangles need to be drawn */
3325 if (data->update_rect1)
3327 if (!RectAndRect(&field_rect, data->update_rect1))
3328 outside = TRUE;
3331 if (data->update_rect2)
3333 if (data->update_rect1)
3335 if ((outside == TRUE) && RectAndRect(&field_rect, data->update_rect2))
3336 outside = FALSE;
3338 else
3340 if (!RectAndRect(&field_rect, data->update_rect2))
3341 outside = TRUE;
3345 if (outside != TRUE)
3347 RenderListViewModeHeaderField(obj, data, &field_rect, index, FALSE);
3348 x += data->icld_LVMAttribs->lmva_ColumnWidth[index];
3350 #if defined(DEBUG_ILC_ICONRENDERING)
3351 else
3353 D(bug("[IconList] %s: Column '%s' outside of update area .. skipping\n", __PRETTY_FUNCTION__, data->icld_LVMAttribs->lmva_ColumnTitle[i]));
3355 #endif
3358 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_HEADERDRAWTOEND) == LVMAF_HEADERDRAWTOEND)
3360 x += HEADERLINE_SPACING_RIGHT;
3362 if (x < linerect.MaxX)
3364 linerect.MinX = x;
3366 // if (MustRenderRect(data, &linerect))
3367 // {
3368 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_HALFSHINE], 0, JAM1);
3369 RectFill(data->icld_BufferRastPort, linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
3370 // }
3376 ///MUIM_Draw()
3377 /**************************************************************************
3378 MUIM_Draw - draw the IconList
3379 **************************************************************************/
3380 IPTR DrawCount;
3381 IPTR IconList__MUIM_Draw(struct IClass *CLASS, Object *obj, struct MUIP_Draw *message)
3383 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3384 struct IconEntry *entry = NULL;
3386 APTR clip = NULL;
3388 ULONG update_oldwidth = 0,
3389 update_oldheight = 0;
3391 LONG clear_xoffset = 0,
3392 clear_yoffset = 0;
3394 __unused IPTR draw_id = DrawCount++;
3396 #if defined(DEBUG_ILC_FUNCS)
3397 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
3398 #endif
3399 #if defined(DEBUG_ILC_ICONRENDERING)
3400 D(bug("[IconList] %s: id %d\n", __PRETTY_FUNCTION__, draw_id));
3401 #endif
3403 DoSuperMethodA(CLASS, obj, (Msg)message);
3405 if (!(data->icld__Option_IconListFixedBackground))
3407 clear_xoffset = data->icld_ViewX;
3408 clear_yoffset = data->icld_ViewY;
3411 // If window size changes, only update needed areas
3412 if (data->update_oldwidth == 0) data->update_oldwidth = data->icld_ViewWidth;
3413 if (data->update_oldheight == 0) data->update_oldheight = data->icld_ViewHeight;
3414 if ((data->update_oldwidth != data->icld_ViewWidth) || (data->update_oldheight != data->icld_ViewHeight))
3416 if (data->icld_UpdateMode != UPDATE_SCROLL)
3418 data->icld_UpdateMode = UPDATE_RESIZE;
3419 update_oldwidth = data->update_oldwidth;
3420 update_oldheight = data->update_oldheight;
3421 data->update_oldwidth = data->icld_ViewWidth;
3422 data->update_oldheight = data->icld_ViewHeight;
3426 if ((message->flags & MADF_DRAWUPDATE) || (data->icld_UpdateMode == UPDATE_RESIZE))
3428 #if defined(DEBUG_ILC_ICONRENDERING)
3430 if (message->flags & MADF_DRAWUPDATE)
3432 bug("[IconList] %s#%d: MADF_DRAWUPDATE\n", __PRETTY_FUNCTION__, draw_id);
3434 else
3436 bug("[IconList] %s#%d: UPDATE_RESIZE\n", __PRETTY_FUNCTION__, draw_id);
3439 #endif
3440 if ((data->icld_UpdateMode == UPDATE_HEADERENTRY) && ((IPTR)data->update_entry < NUM_COLUMNS)) /* draw the header entry */
3442 struct Rectangle field_rect;
3443 LONG index, i, firstvis, lastvis;
3445 firstvis = FirstVisibleColumnNumber(data);
3446 lastvis = LastVisibleColumnNumber(data);
3448 field_rect.MinX = _mleft(obj) - data->icld_ViewX;
3450 field_rect.MinY = _mtop(obj);
3451 field_rect.MaxY = field_rect.MinY + data->icld_LVMAttribs->lmva_HeaderHeight - 1;
3453 for(i = 0; i < NUM_COLUMNS; i++)
3455 index = data->icld_LVMAttribs->lmva_ColumnPos[i];
3456 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
3458 field_rect.MaxX = field_rect.MinX + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1;
3459 if (index == lastvis)
3460 field_rect.MaxX += HEADERLINE_SPACING_RIGHT;
3462 if ((IPTR)data->update_entry != index)
3464 field_rect.MinX += data->icld_LVMAttribs->lmva_ColumnWidth[index];
3465 if (index == firstvis)
3466 field_rect.MinX += HEADERLINE_SPACING_LEFT;
3468 else
3469 break;
3472 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mright(obj) - _mleft(obj) + 1, data->icld_LVMAttribs->lmva_HeaderHeight);
3474 if (data->icld_LVMAttribs->lmva_LastSelectedColumn == (IPTR)data->update_entry)
3475 RenderListViewModeHeaderField(obj, data, &field_rect, (IPTR)data->update_entry, TRUE);
3476 else
3477 RenderListViewModeHeaderField(obj, data, &field_rect, (IPTR)data->update_entry, FALSE);
3479 data->icld_UpdateMode = 0;
3480 data->update_entry = NULL;
3482 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3484 #if defined(DEBUG_ILC_ICONRENDERING)
3485 D(bug("[IconList] %s#%d: UPDATE_HEADERENTRY Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3486 #endif
3487 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3488 field_rect.MinX - _mleft(obj), field_rect.MinY - _mtop(obj),
3489 data->icld_DisplayRastPort,
3490 field_rect.MinX, field_rect.MinY,
3491 field_rect.MaxX - field_rect.MinX + 1, field_rect.MaxY - field_rect.MinY + 1,
3492 0xC0);
3494 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3496 goto draw_done;
3498 else if ((data->icld_UpdateMode == UPDATE_SINGLEENTRY) && (data->update_entry != NULL)) /* draw only a single entry at update_entry */
3500 struct Rectangle rect;
3502 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3504 LONG count = 0, index = -1;
3506 #if defined(DEBUG_ILC_ICONRENDERING)
3507 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY + ICONLIST_DISP_MODELIST\n", __PRETTY_FUNCTION__, draw_id));
3508 #endif
3509 rect.MinX = _mleft(obj);
3510 rect.MaxX = _mleft(obj) + _mwidth(obj) - 1;
3512 ForeachNode(&data->icld_IconList, entry)
3514 if (entry == data->update_entry)
3516 index = count;
3517 break;
3519 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
3521 count++;
3525 if (index != -1)
3527 rect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight - data->icld_ViewY + (index * data->icld_LVMAttribs->lmva_RowHeight);
3528 rect.MaxY = rect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
3530 if ((rect.MaxY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight))
3531 || (rect.MinY > (_mtop(obj) + _mheight(obj) - 1)))
3532 goto draw_done;
3534 if (rect.MinY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight)) rect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight;
3535 if (rect.MaxY > (_mtop(obj) + _mheight(obj) - 1)) rect.MaxY = _mtop(obj) + _mheight(obj) - 1;
3537 clip = MUI_AddClipping(muiRenderInfo(obj), rect.MinX, rect.MinY, rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1);
3539 DoMethod(obj, MUIM_DrawBackground,
3540 rect.MinX, rect.MinY,
3541 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3542 clear_xoffset, clear_yoffset,
3545 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3546 DoMethod(obj, MUIM_IconList_DrawEntry, data->update_entry, index);
3547 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3548 data->icld_UpdateMode = 0;
3549 data->update_entry = NULL;
3552 else
3554 #if defined(DEBUG_ILC_ICONRENDERING)
3555 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY (entry @ 0x%p)\n", __PRETTY_FUNCTION__, draw_id, data->update_entry));
3556 #endif
3557 IconList_GetIconAreaRectangle(obj, data, data->update_entry, &rect);
3559 rect.MinX += _mleft(obj) + (data->update_entry->ie_IconX - data->icld_ViewX);
3560 rect.MaxX += _mleft(obj) + (data->update_entry->ie_IconX - data->icld_ViewX);
3561 rect.MinY += _mtop(obj) + (data->update_entry->ie_IconY - data->icld_ViewY);
3562 rect.MaxY += _mtop(obj) + (data->update_entry->ie_IconY - data->icld_ViewY);
3564 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
3566 if (data->update_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
3568 rect.MinX += ((data->icld_IconAreaLargestWidth - data->update_entry->ie_AreaWidth)/2);
3569 rect.MaxX += ((data->icld_IconAreaLargestWidth - data->update_entry->ie_AreaWidth)/2);
3572 if (data->update_entry->ie_AreaHeight < data->icld_IconAreaLargestHeight)
3574 rect.MinY += ((data->icld_IconAreaLargestHeight - data->update_entry->ie_AreaHeight)/2);
3575 rect.MaxY += ((data->icld_IconAreaLargestHeight - data->update_entry->ie_AreaHeight)/2);
3579 if (rect.MinX < _mleft(obj)) rect.MinX = _mleft(obj);
3580 if (rect.MaxX > _mright(obj)) rect.MaxX =_mright(obj);
3581 if (rect.MinY < _mtop(obj)) rect.MinY = _mtop(obj);
3582 if (rect.MaxY > _mbottom(obj)) rect.MaxY = _mbottom(obj);
3584 clip = MUI_AddClipping(muiRenderInfo(obj), rect.MinX, rect.MinY, rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1);
3586 #if defined(DEBUG_ILC_ICONRENDERING)
3587 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY: Calling MUIM_DrawBackground (A)\n", __PRETTY_FUNCTION__, draw_id));
3588 #endif
3589 DoMethod(obj, MUIM_DrawBackground,
3590 rect.MinX, rect.MinY,
3591 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3592 clear_xoffset, clear_yoffset,
3595 /* We could have deleted also other icons so they must be redrawn */
3596 #if defined(__AROS__)
3597 ForeachNode(&data->icld_IconList, entry)
3598 #else
3599 Foreach_Node(&data->icld_IconList, entry);
3600 #endif
3602 if ((entry != data->update_entry) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
3604 struct Rectangle rect2;
3605 IconList_GetIconAreaRectangle(obj, data, entry, &rect2);
3607 rect2.MinX += _mleft(obj) - data->icld_ViewX + entry->ie_IconX;
3608 rect2.MaxX += _mleft(obj) - data->icld_ViewX + entry->ie_IconX;
3609 rect2.MinY += _mtop(obj) - data->icld_ViewY + entry->ie_IconY;
3610 rect2.MaxY += _mtop(obj) - data->icld_ViewY + entry->ie_IconY;
3612 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
3614 if (entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
3616 rect2.MinX += ((data->icld_IconAreaLargestWidth - entry->ie_AreaWidth)/2);
3617 rect2.MaxX += ((data->icld_IconAreaLargestWidth - entry->ie_AreaWidth)/2);
3620 if (entry->ie_AreaHeight < data->icld_IconAreaLargestHeight)
3622 rect2.MinY += ((data->icld_IconAreaLargestHeight - entry->ie_AreaHeight)/2);
3623 rect2.MaxY += ((data->icld_IconAreaLargestHeight - entry->ie_AreaHeight)/2);
3627 if (RectAndRect(&rect, &rect2))
3629 // Update entry here
3630 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3631 DoMethod(obj, MUIM_IconList_DrawEntry, entry, ICONENTRY_DRAWMODE_PLAIN);
3632 DoMethod(obj, MUIM_IconList_DrawEntryLabel, entry, ICONENTRY_DRAWMODE_PLAIN);
3633 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3638 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3639 DoMethod(obj, MUIM_IconList_DrawEntry, data->update_entry, ICONENTRY_DRAWMODE_PLAIN);
3640 DoMethod(obj, MUIM_IconList_DrawEntryLabel, data->update_entry, ICONENTRY_DRAWMODE_PLAIN);
3641 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3642 data->icld_UpdateMode = 0;
3643 data->update_entry = NULL;
3645 if (data->update_entry == NULL)
3647 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3649 #if defined(DEBUG_ILC_ICONRENDERING)
3650 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3651 #endif
3652 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3653 rect.MinX - _mleft(obj), rect.MinY - _mtop(obj),
3654 data->icld_DisplayRastPort,
3655 rect.MinX, rect.MinY,
3656 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3657 0xC0);
3659 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3661 goto draw_done;
3663 else if (data->icld_UpdateMode == UPDATE_SCROLL)
3665 struct Region *region = NULL;
3666 struct Rectangle xrect,
3667 yrect;
3668 BOOL scroll_caused_damage = FALSE;
3670 #if defined(DEBUG_ILC_ICONRENDERING)
3671 D(bug("[IconList] %s#%d: UPDATE_SCROLL.\n", __PRETTY_FUNCTION__, draw_id));
3672 #endif
3674 if (!data->icld__Option_IconListFixedBackground)
3676 scroll_caused_damage = (_rp(obj)->Layer->Flags & LAYERREFRESH) ? FALSE : TRUE;
3678 data->icld_UpdateMode = 0;
3680 if ((abs(data->update_scrolldx) >= _mwidth(obj)) ||
3681 (abs(data->update_scrolldy) >= _mheight(obj)))
3683 #if defined(DEBUG_ILC_ICONRENDERING)
3684 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Moved outside current view -> Causing Redraw .. MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3685 #endif
3686 MUI_Redraw(obj, MADF_DRAWOBJECT);
3687 goto draw_done;
3690 if (!(region = NewRegion()))
3692 #if defined(DEBUG_ILC_ICONRENDERING)
3693 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Couldnt Alloc Region -> Causing Redraw ...MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3694 #endif
3695 MUI_Redraw(obj, MADF_DRAWOBJECT);
3696 goto draw_done;
3699 if (data->update_scrolldx > 0)
3701 xrect.MinX = _mright(obj) - data->update_scrolldx;
3702 xrect.MinY = _mtop(obj);
3703 xrect.MaxX = _mright(obj);
3704 xrect.MaxY = _mbottom(obj);
3706 OrRectRegion(region, &xrect);
3708 data->update_rect1 = &xrect;
3710 else if (data->update_scrolldx < 0)
3712 xrect.MinX = _mleft(obj);
3713 xrect.MinY = _mtop(obj);
3714 xrect.MaxX = _mleft(obj) - data->update_scrolldx;
3715 xrect.MaxY = _mbottom(obj);
3717 OrRectRegion(region, &xrect);
3719 data->update_rect1 = &xrect;
3722 if (data->update_scrolldy > 0)
3724 yrect.MinX = _mleft(obj);
3725 yrect.MinY = _mbottom(obj) - data->update_scrolldy;
3726 if (((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3727 && (yrect.MinY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight)))
3729 xrect.MinY = data->icld_LVMAttribs->lmva_HeaderHeight;
3731 yrect.MaxX = _mright(obj);
3732 yrect.MaxY = _mbottom(obj);
3734 OrRectRegion(region, &yrect);
3736 data->update_rect2 = &yrect;
3738 else if (data->update_scrolldy < 0)
3740 yrect.MinX = _mleft(obj);
3741 yrect.MinY = _mtop(obj);
3742 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3744 xrect.MinY += data->icld_LVMAttribs->lmva_HeaderHeight;
3746 yrect.MaxX = _mright(obj);
3747 yrect.MaxY = _mtop(obj) - data->update_scrolldy;
3749 OrRectRegion(region, &yrect);
3751 data->update_rect2 = &yrect;
3754 #if defined(DEBUG_ILC_ICONRENDERING)
3755 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Scrolling Raster..\n", __PRETTY_FUNCTION__, draw_id));
3756 #endif
3757 if (data->icld_DisplayRastPort == data->icld_BufferRastPort)
3759 ScrollRasterBF(data->icld_BufferRastPort,
3760 data->update_scrolldx,
3761 data->update_scrolldy,
3762 _mleft(obj),
3763 _mtop(obj),
3764 _mright(obj),
3765 _mbottom(obj));
3767 else
3769 ScrollRasterBF(data->icld_BufferRastPort,
3770 data->update_scrolldx,
3771 data->update_scrolldy,
3774 _mwidth(obj) - 1,
3775 _mheight(obj) - 1);
3778 scroll_caused_damage = scroll_caused_damage && (_rp(obj)->Layer->Flags & LAYERREFRESH) ? TRUE : FALSE;
3780 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
3783 #if defined(DEBUG_ILC_ICONRENDERING)
3784 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3785 #endif
3786 MUI_Redraw(obj, MADF_DRAWOBJECT);
3788 data->update_rect1 = data->update_rect2 = NULL;
3790 if (!data->icld__Option_IconListFixedBackground)
3792 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
3794 if (scroll_caused_damage)
3796 if (MUI_BeginRefresh(muiRenderInfo(obj), 0))
3798 /* Theoretically it might happen that more damage is caused
3799 after ScrollRaster. By something else, like window movement
3800 in front of our window. Therefore refresh root object of
3801 window, not just this object */
3803 Object *o = NULL;
3805 GET(_win(obj),MUIA_Window_RootObject, &o);
3806 MUI_Redraw(o, MADF_DRAWOBJECT);
3807 #if defined(DEBUG_ILC_ICONRENDERING)
3808 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3809 #endif
3810 MUI_EndRefresh(muiRenderInfo(obj), 0);
3814 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3816 #if defined(DEBUG_ILC_ICONRENDERING)
3817 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3818 #endif
3819 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3820 0, 0,
3821 data->icld_DisplayRastPort,
3822 _mleft(obj), _mtop(obj),
3823 _mwidth(obj), _mheight(obj),
3824 0xC0);
3826 goto draw_done;
3828 else if (data->icld_UpdateMode == UPDATE_RESIZE)
3830 struct Region *region = NULL;
3831 struct Rectangle wrect,
3832 hrect;
3833 ULONG diffw = 0,
3834 diffh = 0;
3836 #if defined(DEBUG_ILC_ICONRENDERING)
3837 D(bug("[IconList] %s#%d: UPDATE_RESIZE.\n", __PRETTY_FUNCTION__, draw_id));
3838 #endif
3840 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
3842 //Free up the buffers Layer, rastport and bitmap so we can replace them ..
3843 if ((GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_WIDTH) != data->icld_ViewWidth)
3844 || (GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_HEIGHT) != data->icld_ViewHeight))
3846 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
3847 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
3848 D(bug("[IconList] %s: Destroying old BackLayer\n", __PRETTY_FUNCTION__));
3849 #endif
3850 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3851 DeleteLayer(0, oldLayer);
3854 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
3856 struct BitMap *bitmap_New;
3857 ULONG tmp_RastDepth;
3858 struct Layer_Info *li = NULL;
3860 tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
3861 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
3862 data->icld_ViewHeight,
3863 tmp_RastDepth,
3864 BMF_CLEAR,
3865 data->icld_DisplayRastPort->BitMap)) != NULL)
3867 if ((data->icld_BufferRastPort = CreateRastPort()) != NULL)
3869 data->icld_BufferRastPort->BitMap = bitmap_New;
3870 if ((li = NewLayerInfo()))
3872 if ((data->icld_BufferRastPort->Layer = CreateUpfrontLayer(li, data->icld_BufferRastPort->BitMap, 0, 0, data->icld_ViewWidth - 1, data->icld_ViewHeight - 1, 0, NULL)))
3875 * Mark it as a buffered rastport.
3878 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
3879 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
3880 #endif
3881 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
3882 data->icld_DrawOffsetX = 0;
3883 data->icld_DrawOffsetY = 0;
3885 else
3886 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3888 else
3889 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3891 else
3892 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3895 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
3897 if (bitmap_New) FreeBitMap(bitmap_New);
3898 if (li) DisposeLayerInfo(li);
3899 data->icld_DrawOffsetX = _mleft(obj);
3900 data->icld_DrawOffsetY = _mtop(obj);
3905 data->icld_UpdateMode = 0;
3907 if (!data->icld__Option_IconListScaledBackground)
3909 if (!(region = NewRegion()))
3911 #if defined(DEBUG_ILC_ICONRENDERING)
3912 D(bug("[IconList] %s#%d: UPDATE_RESIZE: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3913 #endif
3914 MUI_Redraw(obj, MADF_DRAWOBJECT);
3915 goto draw_done;
3918 if ( data->icld_ViewWidth > update_oldwidth )
3919 diffw = data->icld_ViewWidth - update_oldwidth;
3920 if ( data->icld_ViewHeight > update_oldheight )
3921 diffh = data->icld_ViewHeight - update_oldheight;
3923 if (diffw)
3925 wrect.MinX = _mright(obj) - diffw;
3926 wrect.MinY = _mtop(obj);
3927 wrect.MaxX = _mright(obj);
3928 wrect.MaxY = _mbottom(obj);
3929 OrRectRegion(region, &wrect);
3930 data->update_rect1 = &wrect;
3933 if (diffh)
3935 hrect.MinX = _mleft(obj);
3936 hrect.MinY = _mbottom(obj) - diffh;
3937 hrect.MaxX = _mright(obj);
3938 hrect.MaxX = _mright(obj);
3939 hrect.MaxY = _mbottom(obj);
3940 OrRectRegion(region, &hrect);
3941 data->update_rect2 = &hrect;
3943 if (diffh||diffw)
3945 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
3947 else
3949 /* View became smaller both in horizontal and vertical direction.
3950 Nothing to do */
3952 DisposeRegion(region);
3953 goto draw_done;
3957 #if defined(DEBUG_ILC_ICONRENDERING)
3958 D(bug("[IconList] %s#%d: UPDATE_RESIZE: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3959 #endif
3960 MUI_Redraw(obj, MADF_DRAWOBJECT);
3962 if (!data->icld__Option_IconListScaledBackground)
3964 if (diffh||diffw)
3966 data->update_rect1 = data->update_rect2 = NULL;
3967 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
3968 } else DisposeRegion(region);
3971 goto draw_done;
3975 if (message->flags & MADF_DRAWOBJECT)
3977 struct Rectangle viewrect;
3978 int current = 0, first = 0, visible = 0;
3980 #if defined(DEBUG_ILC_ICONRENDERING)
3981 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3982 #endif
3984 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3986 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), data->icld_LVMAttribs->lmva_HeaderHeight);
3987 RenderListViewModeHeader(obj, data);
3989 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3991 #if defined(DEBUG_ILC_ICONRENDERING)
3992 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT Blitting Header to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3993 #endif
3994 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3995 0, 0,
3996 data->icld_DisplayRastPort,
3997 _mleft(obj), _mtop(obj), _mwidth(obj), data->icld_LVMAttribs->lmva_HeaderHeight,
3998 0xC0);
4001 MUI_RemoveClipping(muiRenderInfo(obj), clip);
4003 viewrect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight;
4005 first = FirstVisibleLine(data);
4006 visible = NumVisibleLines(data);
4008 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight, _mwidth(obj), _mheight(obj) - data->icld_LVMAttribs->lmva_HeaderHeight);
4010 else
4012 viewrect.MinY = _mtop(obj);
4013 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj));
4016 viewrect.MaxY = _mtop(obj) + _mheight(obj) - 1;
4017 viewrect.MinX = _mleft(obj);
4018 viewrect.MaxX = _mleft(obj) + _mwidth(obj) - 1;
4020 #if defined(DEBUG_ILC_ICONRENDERING)
4021 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT: Calling MUIM_DrawBackground (B)\n", __PRETTY_FUNCTION__, draw_id));
4022 #endif
4023 DoMethod(
4024 obj, MUIM_DrawBackground, viewrect.MinX, viewrect.MinY, (viewrect.MaxX - viewrect.MinX) + 1, (viewrect.MaxY - viewrect.MinY) + 1,
4025 clear_xoffset, clear_yoffset, 0
4027 #if defined(__AROS__)
4028 ForeachNode(&data->icld_IconList, entry)
4029 #else
4030 Foreach_Node(&data->icld_IconList, entry);
4031 #endif
4033 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
4035 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4037 if ((current >= first) && (current <= (first + visible)))
4039 DoMethod(obj, MUIM_IconList_DrawEntry, entry, current);
4041 current++;
4044 else
4046 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
4047 (entry->ie_DiskObj) &&
4048 (entry->ie_IconX != NO_ICON_POSITION) &&
4049 (entry->ie_IconY != NO_ICON_POSITION))
4051 struct Rectangle iconrect;
4052 IconList_GetIconAreaRectangle(obj, data, entry, &iconrect);
4054 iconrect.MinX += viewrect.MinX - data->icld_ViewX + entry->ie_IconX;
4055 iconrect.MaxX += viewrect.MinX - data->icld_ViewX + entry->ie_IconX;
4056 iconrect.MinY += viewrect.MinY - data->icld_ViewY + entry->ie_IconY;
4057 iconrect.MaxY += viewrect.MinY - data->icld_ViewY + entry->ie_IconY;
4059 if (RectAndRect(&viewrect, &iconrect))
4061 DoMethod(obj, MUIM_IconList_DrawEntry, entry, ICONENTRY_DRAWMODE_PLAIN);
4062 DoMethod(obj, MUIM_IconList_DrawEntryLabel, entry, ICONENTRY_DRAWMODE_PLAIN);
4068 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
4070 #if defined(DEBUG_ILC_ICONRENDERING)
4071 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT: Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
4072 #endif
4073 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
4074 0, 0,
4075 data->icld_DisplayRastPort,
4076 _mleft(obj), _mtop(obj),
4077 _mwidth(obj), _mheight(obj),
4078 0xC0);
4081 MUI_RemoveClipping(muiRenderInfo(obj), clip);
4083 data->icld_UpdateMode = 0;
4085 draw_done:;
4087 #if defined(DEBUG_ILC_ICONRENDERING)
4088 D(bug("[IconList] %s: Draw finished for id %d\n", __PRETTY_FUNCTION__, draw_id));
4089 #endif
4090 return 0;
4094 ///IconList__MUIM_IconList_Update()
4095 /**************************************************************************
4096 MUIM_IconList_Refresh
4097 Implemented by subclasses
4098 **************************************************************************/
4099 IPTR IconList__MUIM_IconList_Update(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Update *message)
4101 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4103 #if defined(DEBUG_ILC_FUNCS)
4104 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4105 #endif
4107 data->icld_FocusIcon = NULL;
4108 SET(obj, MUIA_IconList_Changed, TRUE);
4110 return 1;
4114 ///MUIM_IconList_Clear()
4115 /**************************************************************************
4116 MUIM_IconList_Clear
4117 **************************************************************************/
4118 IPTR IconList__MUIM_IconList_Clear(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Clear *message)
4120 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4121 struct IconEntry *node = NULL;
4123 #if defined(DEBUG_ILC_FUNCS)
4124 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4125 #endif
4127 while ((node = (struct IconEntry*)RemTail((struct List*)&data->icld_IconList)))
4129 DoMethod(obj, MUIM_IconList_DestroyEntry, node);
4132 data->icld_SelectionLastClicked = NULL;
4133 data->icld_FocusIcon = NULL;
4135 data->icld_ViewX = data->icld_ViewY = data->icld_AreaWidth = data->icld_AreaHeight = 0;
4136 data->icld_IconAreaLargestWidth = 0;
4137 data->icld_IconAreaLargestHeight = 0;
4138 data->icld_IconLargestHeight = 0;
4139 data->icld_LabelLargestHeight = 0;
4141 #if defined(DEBUG_ILC_ICONRENDERING)
4142 D(bug("[IconList]: %s: call SetSuperAttrs()\n", __PRETTY_FUNCTION__));
4143 #endif
4144 SetSuperAttrs(CLASS, obj, MUIA_Virtgroup_Left, data->icld_ViewX,
4145 MUIA_Virtgroup_Top, data->icld_ViewY,
4146 TAG_DONE);
4148 #if defined(DEBUG_ILC_ICONRENDERING)
4149 D(bug("[IconList]: %s: call SetAttrs()\n", __PRETTY_FUNCTION__));
4150 #endif
4151 SetAttrs(obj, MUIA_Virtgroup_Left, data->icld_ViewX,
4152 MUIA_Virtgroup_Top, data->icld_ViewY,
4153 TAG_DONE);
4155 #if defined(DEBUG_ILC_ICONRENDERING)
4156 D(bug("[IconList]: %s: Set MUIA_IconList_Width and MUIA_IconList_Height\n", __PRETTY_FUNCTION__));
4157 #endif
4158 SetAttrs(obj, MUIA_IconList_Width, data->icld_AreaWidth,
4159 MUIA_IconList_Height, data->icld_AreaHeight,
4160 TAG_DONE);
4162 D(bug("[IconList]: %s: call MUI_Redraw()\n", __PRETTY_FUNCTION__));
4163 MUI_Redraw(obj,MADF_DRAWOBJECT);
4164 return 1;
4168 ///IconList__MUIM_IconList_DestroyEntry()
4169 IPTR IconList__MUIM_IconList_DestroyEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DestroyEntry *message)
4171 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4173 #if defined(DEBUG_ILC_FUNCS)
4174 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4175 #endif
4177 if (message->entry)
4179 if (message->entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
4181 if (data->icld_SelectionLastClicked == message->entry)
4183 struct IconList_Entry *nextentry = &message->entry->ie_IconListEntry;
4185 /* get selected entries from SOURCE iconlist */
4186 DoMethod(obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&nextentry);
4187 if ((nextentry) && ((IPTR)nextentry != MUIV_IconList_NextIcon_End))
4188 data->icld_SelectionLastClicked = (struct IconEntry *)((IPTR)nextentry - ((IPTR)&message->entry->ie_IconListEntry - (IPTR)message->entry));
4189 else
4190 data->icld_SelectionLastClicked = NULL;
4192 if (data->icld_FocusIcon == message->entry)
4193 data->icld_FocusIcon = data->icld_SelectionLastClicked;
4195 Remove(&message->entry->ie_SelectionNode);
4198 if (message->entry->ie_TxtBuf_DisplayedLabel)
4199 FreeVecPooled(data->icld_Pool, message->entry->ie_TxtBuf_DisplayedLabel);
4201 if (message->entry->ie_TxtBuf_PROT)
4202 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_PROT, 8);
4204 if (message->entry->ie_TxtBuf_SIZE)
4205 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_SIZE, 30);
4207 if (message->entry->ie_TxtBuf_TIME)
4208 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_TIME, LEN_DATSTRING);
4210 if (message->entry->ie_TxtBuf_DATE)
4211 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_DATE, LEN_DATSTRING);
4213 if (message->entry->ie_DiskObj)
4214 FreeDiskObject(message->entry->ie_DiskObj);
4216 if (message->entry->ie_FileInfoBlock)
4217 FreeMem(message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4219 if (message->entry->ie_IconListEntry.label)
4220 FreePooled(data->icld_Pool, message->entry->ie_IconListEntry.label, strlen(message->entry->ie_IconListEntry.label)+1);
4222 if (message->entry->ie_IconNode.ln_Name)
4223 FreePooled(data->icld_Pool, message->entry->ie_IconNode.ln_Name, strlen(message->entry->ie_IconNode.ln_Name)+1);
4225 FreePooled(data->icld_Pool, message->entry, sizeof(struct IconEntry));
4227 return (IPTR)TRUE;
4231 ///IconList__MUIM_IconList_PropagateEntryPos()
4232 IPTR IconList__MUIM_IconList_PropagateEntryPos(struct IClass *CLASS, Object *obj,
4233 struct MUIP_IconList_PropagateEntryPos *message)
4235 message->entry->ie_ProvidedIconX = message->entry->ie_IconX;
4236 message->entry->ie_ProvidedIconY = message->entry->ie_IconY;
4238 return (IPTR)TRUE;
4242 ///IconList__MUIM_IconList_CreateEntry()
4243 /**************************************************************************
4244 MUIM_IconList_CreateEntry.
4245 Returns 0 on failure; otherwise it returns the icon's entry.
4246 **************************************************************************/
4247 IPTR IconList__MUIM_IconList_CreateEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_CreateEntry *message)
4249 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4250 struct IconEntry *entry = NULL;
4251 struct DateTime dt;
4252 struct DateStamp now;
4253 UBYTE *sp = NULL;
4255 struct DiskObject *dob = NULL;
4256 struct Rectangle rect;
4258 IPTR geticon_error = 0;
4260 #if defined(DEBUG_ILC_FUNCS)
4261 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4262 #endif
4264 if (message->filename == NULL) {
4265 D(bug("[IconList] %s: IconList - filename was NULL\n", __PRETTY_FUNCTION__));
4266 return (IPTR)NULL;
4269 /*disk object (icon)*/
4270 if (message->entry_dob == NULL)
4272 IPTR iconlistScreen = (IPTR)_screen(obj);
4273 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
4275 dob = GetIconTags
4277 message->filename,
4278 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
4279 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
4280 ICONGETA_FailIfUnavailable, FALSE,
4281 ICONGETA_GenerateImageMasks, TRUE,
4282 ICONA_ErrorCode, &geticon_error,
4283 TAG_DONE
4286 if (dob == NULL)
4288 D(bug("[IconList] %s: Fatal: Couldnt get DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
4290 return (IPTR)NULL;
4293 else
4295 dob = message->entry_dob;
4298 D(bug("[IconList] %s: DiskObject @ 0x%p\n", __PRETTY_FUNCTION__, dob));
4300 if ((entry = AllocPooled(data->icld_Pool, sizeof(struct IconEntry))) == NULL)
4302 D(bug("[IconList] %s: Failed to Allocate Entry Storage!\n", __PRETTY_FUNCTION__));
4303 FreeDiskObject(dob);
4304 return (IPTR)NULL;
4306 memset(entry, 0, sizeof(struct IconEntry));
4307 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4308 entry->ie_IconListEntry.ile_IconEntry = entry;
4310 /* Allocate Text Buffers */
4312 if ((entry->ie_TxtBuf_DATE = AllocPooled(data->icld_Pool, LEN_DATSTRING)) == NULL)
4314 D(bug("[IconList] %s: Failed to Allocate Entry DATE Storage!\n", __PRETTY_FUNCTION__));
4315 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4316 return (IPTR)NULL;
4318 memset(entry->ie_TxtBuf_DATE, 0, LEN_DATSTRING);
4320 if ((entry->ie_TxtBuf_TIME = AllocPooled(data->icld_Pool, LEN_DATSTRING)) == NULL)
4322 D(bug("[IconList] %s: Failed to Allocate Entry TIME string Storage!\n", __PRETTY_FUNCTION__));
4323 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4324 return (IPTR)NULL;
4326 memset(entry->ie_TxtBuf_TIME, 0, LEN_DATSTRING);
4328 if ((entry->ie_TxtBuf_SIZE = AllocPooled(data->icld_Pool, 30)) == NULL)
4330 D(bug("[IconList] %s: Failed to Allocate Entry SIZE string Storage!\n", __PRETTY_FUNCTION__));
4331 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4332 return (IPTR)NULL;
4334 memset(entry->ie_TxtBuf_SIZE, 0, 30);
4336 if ((entry->ie_TxtBuf_PROT = AllocPooled(data->icld_Pool, 8)) == NULL)
4338 D(bug("[IconList] %s: Failed to Allocate Entry PROT Flag string Storage!\n", __PRETTY_FUNCTION__));
4339 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4340 return (IPTR)NULL;
4342 memset(entry->ie_TxtBuf_PROT, 0, 8);
4344 /*alloc filename*/
4345 if ((entry->ie_IconNode.ln_Name = AllocPooled(data->icld_Pool, strlen(message->filename) + 1)) == NULL)
4347 D(bug("[IconList] %s: Failed to Allocate Entry filename string Storage!\n", __PRETTY_FUNCTION__));
4348 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4349 return (IPTR)NULL;
4352 /*alloc entry label*/
4353 if ((entry->ie_IconListEntry.label = AllocPooled(data->icld_Pool, strlen(message->label) + 1)) == NULL)
4355 D(bug("[IconList] %s: Failed to Allocate Entry label string Storage!\n", __PRETTY_FUNCTION__));
4356 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4357 return (IPTR)NULL;
4360 /*file info block*/
4361 if(message->fib != NULL)
4363 if ((entry->ie_FileInfoBlock = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)) != NULL)
4365 CopyMem(message->fib, entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4367 if (entry->ie_FileInfoBlock->fib_DirEntryType > 0)
4369 strcpy(entry->ie_TxtBuf_SIZE, "Drawer");
4371 else
4373 FmtSizeToString(entry->ie_TxtBuf_SIZE, entry->ie_FileInfoBlock->fib_Size);
4376 dt.dat_Stamp = entry->ie_FileInfoBlock->fib_Date;
4377 dt.dat_Format = FORMAT_DEF;
4378 dt.dat_Flags = 0;
4379 dt.dat_StrDay = NULL;
4380 dt.dat_StrDate = entry->ie_TxtBuf_DATE;
4381 dt.dat_StrTime = entry->ie_TxtBuf_TIME;
4383 DateToStr(&dt);
4384 DateStamp(&now);
4386 /*if modified today show time, otherwise just show date*/
4387 if (now.ds_Days == entry->ie_FileInfoBlock->fib_Date.ds_Days)
4388 entry->ie_Flags |= ICONENTRY_FLAG_TODAY;
4389 else
4390 entry->ie_Flags &= ~ICONENTRY_FLAG_TODAY;
4392 sp = entry->ie_TxtBuf_PROT;
4393 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_SCRIPT) ? 's' : '-';
4394 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_PURE) ? 'p' : '-';
4395 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
4396 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_READ) ? '-' : 'r';
4397 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_WRITE) ? '-' : 'w';
4398 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
4399 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_DELETE) ? '-' : 'd';
4400 *sp++ = '\0';
4402 entry->ie_IconListEntry.type = entry->ie_FileInfoBlock->fib_DirEntryType;
4405 else
4407 entry->ie_IconListEntry.type = ST_USERDIR;
4410 /* Override type if specified during CreateEntry */
4411 if (message->type != 0)
4413 entry->ie_IconListEntry.type = message->type;
4414 D(bug("[IconList] %s: Overide Entry Type. New Type = %x\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.type));
4416 else
4418 D(bug("[IconList] %s: Entry Type = %x\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.type));
4421 strcpy(entry->ie_IconNode.ln_Name, message->filename);
4422 strcpy(entry->ie_IconListEntry.label, message->label);
4424 entry->ie_IconListEntry.udata = message->udata;
4426 entry->ie_IconX = dob->do_CurrentX;
4427 entry->ie_IconY = dob->do_CurrentY;
4429 DoMethod(obj, MUIM_IconList_PropagateEntryPos, entry);
4431 if (IconList__LabelFunc_CreateLabel(obj, data, entry) != (IPTR)NULL)
4433 entry->ie_DiskObj = dob;
4435 /* Use a geticonrectangle routine that gets textwidth! */
4436 IconList_GetIconAreaRectangle(obj, data, entry, &rect);
4438 return (IPTR)entry;
4441 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4442 return (IPTR)NULL;
4446 ///IconList__MUIM_IconList_UpdateEntry()
4447 /**************************************************************************
4448 MUIM_IconList_UpdateEntry.
4449 Returns 0 on failure; otherwise it returns the icon's entry.
4450 **************************************************************************/
4451 IPTR IconList__MUIM_IconList_UpdateEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_UpdateEntry *message)
4453 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4454 // struct DateTime dt;
4455 // struct DateStamp now;
4456 // UBYTE *sp = NULL;
4458 // struct DiskObject *dob = NULL;
4459 struct Rectangle rect;
4461 // IPTR geticon_error = 0;
4463 #if defined(DEBUG_ILC_FUNCS)
4464 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4465 #endif
4467 /* Update disk object (icon)*/
4468 /* if (message->entry_dob == NULL)
4470 IPTR iconlistScreen = _screen(obj);
4471 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
4473 dob = GetIconTags
4475 message->filename,
4476 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
4477 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
4478 ICONGETA_FailIfUnavailable, FALSE,
4479 ICONGETA_GenerateImageMasks, TRUE,
4480 ICONA_ErrorCode, &geticon_error,
4481 TAG_DONE
4484 if (dob == NULL)
4486 D(bug("[IconList] %s: Fatal: Couldnt get DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
4488 return (IPTR)NULL;
4491 else
4493 dob = message->entry_dob;
4496 D(bug("[IconList] %s: DiskObject @ 0x%p\n", __PRETTY_FUNCTION__, dob));
4499 /* Update filename */
4500 if (strcmp(message->entry->ie_IconNode.ln_Name, message->filename) != 0)
4502 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4503 FreePooled(data->icld_Pool, message->entry->ie_IconNode.ln_Name, strlen(message->entry->ie_IconNode.ln_Name) + 1);
4504 if ((message->entry->ie_IconNode.ln_Name = AllocPooled(data->icld_Pool, strlen(message->filename) + 1)) == NULL)
4506 D(bug("[IconList] %s: Failed to Allocate Entry filename string Storage!\n", __PRETTY_FUNCTION__));
4507 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4508 return (IPTR)NULL;
4510 strcpy(message->entry->ie_IconNode.ln_Name, message->filename);
4513 /* Update entry label */
4514 if (strcmp(message->entry->ie_IconListEntry.label, message->label) != 0)
4516 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4517 FreePooled(data->icld_Pool, message->entry->ie_IconListEntry.label, strlen(message->entry->ie_IconListEntry.label) + 1);
4518 if ((message->entry->ie_IconListEntry.label = AllocPooled(data->icld_Pool, strlen(message->label) + 1)) == NULL)
4520 D(bug("[IconList] %s: Failed to Allocate Entry label string Storage!\n", __PRETTY_FUNCTION__));
4521 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4522 return (IPTR)NULL;
4524 strcpy(message->entry->ie_IconListEntry.label, message->label);
4525 if (IconList__LabelFunc_CreateLabel(obj, data, message->entry) == (IPTR)NULL)
4527 D(bug("[IconList] %s: Failed to create label\n", __PRETTY_FUNCTION__));
4528 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4529 return (IPTR)NULL;
4533 /* Update file info block */
4534 if(message->fib != NULL)
4536 if (!(message->entry->ie_FileInfoBlock))
4538 if ((message->entry->ie_FileInfoBlock = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)) != NULL)
4540 CopyMem(message->fib, message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4544 /* if (entry->ie_FileInfoBlock->fib_DirEntryType > 0)
4546 strcpy(entry->ie_TxtBuf_SIZE, "Drawer");
4548 else
4550 FmtSizeToString(entry->ie_TxtBuf_SIZE, entry->ie_FileInfoBlock->fib_Size);
4553 dt.dat_Stamp = entry->ie_FileInfoBlock->fib_Date;
4554 dt.dat_Format = FORMAT_DEF;
4555 dt.dat_Flags = 0;
4556 dt.dat_StrDay = NULL;
4557 dt.dat_StrDate = entry->ie_TxtBuf_DATE;
4558 dt.dat_StrTime = entry->ie_TxtBuf_TIME;
4560 DateToStr(&dt);
4561 DateStamp(&now);
4563 //if modified today show time, otherwise just show date
4564 if (now.ds_Days == entry->ie_FileInfoBlock->fib_Date.ds_Days)
4565 entry->ie_Flags |= ICONENTRY_FLAG_TODAY;
4566 else
4567 entry->ie_Flags &= ~ICONENTRY_FLAG_TODAY;
4569 sp = entry->ie_TxtBuf_PROT;
4570 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_SCRIPT) ? 's' : '-';
4571 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_PURE) ? 'p' : '-';
4572 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
4573 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_READ) ? '-' : 'r';
4574 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_WRITE) ? '-' : 'w';
4575 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
4576 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_DELETE) ? '-' : 'd';
4577 *sp++ = '\0';
4579 entry->ie_IconListEntry.type = entry->ie_FileInfoBlock->fib_DirEntryType;
4582 else
4584 if (message->entry->ie_FileInfoBlock)
4586 FreeMem(message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4587 message->entry->ie_FileInfoBlock = NULL;
4589 if (message->entry->ie_IconListEntry.type != ST_USERDIR)
4591 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4592 message->entry->ie_IconListEntry.type = ST_USERDIR;
4596 /* Override type if specified */
4597 if ((message->type != 0) && (message->entry->ie_IconListEntry.type != message->type))
4599 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4600 message->entry->ie_IconListEntry.type = message->type;
4601 D(bug("[IconList] %s: Overide Entry Type. New Type = %x\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.type));
4603 else
4605 D(bug("[IconList] %s: Entry Type = %x\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.type));
4608 IconList_GetIconAreaRectangle(obj, data, message->entry, &rect);
4610 return (IPTR)message->entry;
4614 ///DoWheelMove()
4615 static void DoWheelMove(struct IClass *CLASS, Object *obj, LONG wheelx, LONG wheely, UWORD qual)
4617 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4619 LONG newleft = data->icld_ViewX,
4620 newtop = data->icld_ViewY;
4622 /* Use horizontal scrolling if any of the following cases are true ...
4624 # vertical wheel is used but there's nothing to scroll
4625 (everything is visible already) ..
4627 # vertical wheel is used and one of the ALT keys is down. */
4629 if ((wheely && !wheelx) &&
4630 ((data->icld_AreaHeight <= _mheight(obj)) || (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))))
4632 wheelx = wheely; wheely = 0;
4635 if (qual & (IEQUALIFIER_CONTROL))
4637 if (wheelx < 0) newleft = 0;
4638 if (wheelx > 0) newleft = data->icld_AreaWidth;
4639 if (wheely < 0) newtop = 0;
4640 if (wheely > 0) newtop = data->icld_AreaHeight;
4642 else if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
4644 newleft += (wheelx * _mwidth(obj));
4645 newtop += (wheely * _mheight(obj));
4647 else
4649 newleft += wheelx * 30;
4650 newtop += wheely * 30;
4653 if (newleft + _mwidth(obj) > data->icld_AreaWidth)
4654 newleft = data->icld_AreaWidth - _mwidth(obj);
4655 if (newleft < 0)
4656 newleft = 0;
4658 if (newtop + _mheight(obj) > data->icld_AreaHeight)
4659 newtop = data->icld_AreaHeight - _mheight(obj);
4660 if (newtop < 0)
4661 newtop = 0;
4663 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
4665 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
4666 MUIA_Virtgroup_Top, newtop,
4667 TAG_DONE);
4672 /* Notes:
4674 * LEFTDOWN
4675 * a) if clicked object is selected, nothing
4676 * b) if clicked object is not selected, unselect all, select object
4677 * c) if no clicked object, start lasso
4678 * LEFTUP
4679 * a) if in lasso, finish lasso
4680 * LEFTDOWN + SHIFT
4681 * a) if object is selected, unselect it (= remove from multiselection)
4682 * b) if object is not selected, select it (= add to multiselection)
4685 * Expected behaviour:
4686 * a) you can only "remove" multiselection by clicking on not selected object or on space where there is no icon
4690 static void IconList_HandleNewIconSelection(struct IClass *CLASS, Object *obj, struct MUIP_HandleEvent *message,
4691 struct IconEntry *new_selected, BOOL *doubleclicked)
4693 struct IconEntry *node = NULL;
4694 BOOL update_entry = FALSE;
4695 LONG mx = message->imsg->MouseX - _mleft(obj);
4696 LONG my = message->imsg->MouseY - _mtop(obj);
4697 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4698 BOOL nounselection = (new_selected != NULL &&
4699 (new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED)); /* see notes above */
4702 /* Check if this is a double click on icon or empty space */
4703 if ((DoubleClick(data->last_secs, data->last_mics, message->imsg->Seconds, message->imsg->Micros)) && (data->icld_SelectionLastClicked == new_selected))
4705 #if defined(DEBUG_ILC_EVENTS)
4706 D(bug("[IconList] %s: Entry double-clicked\n", __PRETTY_FUNCTION__));
4707 #endif
4708 *doubleclicked = TRUE;
4711 /* Deselection lopp */
4712 #if defined(__AROS__)
4713 ForeachNode(&data->icld_IconList, node)
4714 #else
4715 Foreach_Node(&data->icld_IconList, node);
4716 #endif
4718 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4720 update_entry = FALSE;
4722 /* If node that is being checked is selected and it is not the clicked node
4723 * and no shift pressed and
4724 * clicked node is not part of selection (see notes above) or this is a double click */
4725 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
4727 if ((new_selected != node) &&
4728 (!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))) &&
4729 (!nounselection || *doubleclicked))
4731 Remove(&node->ie_SelectionNode);
4732 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
4733 update_entry = TRUE;
4737 /* Remove focus */
4738 if ((node->ie_Flags & ICONENTRY_FLAG_FOCUS) && (new_selected != node))
4740 node->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
4741 update_entry = TRUE;
4744 /* Redraw list */
4745 if (update_entry)
4747 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4748 data->update_entry = node;
4749 MUI_Redraw(obj, MADF_DRAWUPDATE);
4750 #if defined(DEBUG_ILC_EVENTS)
4751 D(bug("[IconList] %s: Rendered entry '%s'\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
4752 #endif
4757 if (new_selected != NULL)
4759 /* Found clicked entry... */
4760 data->icld_LassoActive = FALSE;
4761 update_entry = FALSE;
4763 if (!(new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED))
4765 /* Add new entry to selection */
4766 AddTail(&data->icld_SelectionList, &new_selected->ie_SelectionNode);
4767 new_selected->ie_Flags |= ICONENTRY_FLAG_SELECTED;
4768 update_entry = TRUE;
4770 else if ((*doubleclicked == FALSE) && (message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
4772 /* Unselect previously selected entry */
4773 Remove(&new_selected->ie_SelectionNode);
4774 new_selected->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
4775 update_entry = TRUE;
4778 /* Set focus */
4779 if (!(new_selected->ie_Flags & ICONENTRY_FLAG_FOCUS))
4781 new_selected->ie_Flags |= ICONENTRY_FLAG_FOCUS;
4782 data->icld_FocusIcon = new_selected;
4783 update_entry = TRUE;
4786 /* Redraw list */
4787 if (update_entry)
4789 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4790 data->update_entry = new_selected;
4791 MUI_Redraw(obj, MADF_DRAWUPDATE);
4792 #if defined(DEBUG_ILC_EVENTS)
4793 D(bug("[IconList] %s: Rendered 'new_selected' entry '%s'\n", __PRETTY_FUNCTION__, new_selected->ie_IconListEntry.label));
4794 #endif
4797 else
4799 struct Window * thisWindow = NULL;
4800 #if defined(DEBUG_ILC_EVENTS) || defined(DEBUG_ILC_LASSO)
4801 D(bug("[IconList] %s: Starting Lasso\n", __PRETTY_FUNCTION__));
4802 #endif
4803 /* No entry clicked on ... Start Lasso-selection */
4804 data->icld_LassoActive = TRUE;
4805 if (!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
4807 data->icld_SelectionLastClicked = NULL;
4808 data->icld_FocusIcon = NULL;
4810 data->icld_LassoRectangle.MinX = mx - data->view_rect.MinX + data->icld_ViewX;
4811 data->icld_LassoRectangle.MinY = my - data->view_rect.MinY + data->icld_ViewY;
4812 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
4813 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
4815 /* Draw initial Lasso frame */
4816 IconList_InvertLassoOutlines(obj, data, &data->icld_LassoRectangle);
4818 /* Start handling INTUITICKS */
4819 GET(obj, MUIA_Window, &thisWindow);
4820 if (thisWindow)
4822 ModifyIDCMP(thisWindow, (thisWindow->IDCMPFlags|IDCMP_INTUITICKS));
4823 if (!(data->ehn.ehn_Events & IDCMP_INTUITICKS))
4825 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
4826 data->ehn.ehn_Events |= IDCMP_INTUITICKS;
4827 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
4833 ///MUIM_HandleEvent()
4834 /**************************************************************************
4835 MUIM_HandleEvent
4836 **************************************************************************/
4837 IPTR IconList__MUIM_HandleEvent(struct IClass *CLASS, Object *obj, struct MUIP_HandleEvent *message)
4839 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4841 #if defined(DEBUG_ILC_FUNCS)
4842 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4843 #endif
4845 if (message->imsg)
4847 LONG mx = message->imsg->MouseX - _mleft(obj);
4848 LONG my = message->imsg->MouseY - _mtop(obj);
4850 LONG wheelx = 0;
4851 LONG wheely = 0;
4853 switch (message->imsg->Class)
4855 case IDCMP_NEWSIZE:
4856 bug("[IconList] %s: IDCMP_NEWSIZE\n", __PRETTY_FUNCTION__);
4857 break;
4859 case IDCMP_RAWKEY:
4861 #if defined(DEBUG_ILC_EVENTS)
4862 D(bug("[IconList] %s: IDCMP_RAWKEY\n", __PRETTY_FUNCTION__));
4863 #endif
4864 BOOL rawkey_handled = FALSE;
4866 switch(message->imsg->Code)
4868 case RAWKEY_NM_WHEEL_UP:
4869 wheely = -1;
4870 rawkey_handled = TRUE;
4871 break;
4873 case RAWKEY_NM_WHEEL_DOWN:
4874 wheely = 1;
4875 rawkey_handled = TRUE;
4876 break;
4878 case RAWKEY_NM_WHEEL_LEFT:
4879 wheelx = -1;
4880 rawkey_handled = TRUE;
4881 break;
4883 case RAWKEY_NM_WHEEL_RIGHT:
4884 wheelx = 1;
4885 rawkey_handled = TRUE;
4886 break;
4889 if (rawkey_handled)
4891 #if defined(DEBUG_ILC_KEYEVENTS)
4892 D(bug("[IconList] %s: Processing mouse wheel event\n", __PRETTY_FUNCTION__));
4893 #endif
4894 if (_isinobject(message->imsg->MouseX, message->imsg->MouseY) &&
4895 (wheelx || wheely))
4897 DoWheelMove(CLASS, obj, wheelx, wheely, message->imsg->Qualifier);
4900 else if (!(message->imsg->Code & IECODE_UP_PREFIX))
4902 LONG new_ViewY = data->icld_ViewY;
4903 struct IconEntry *start_entry = NULL, *active_entry = NULL, *entry_next = NULL;
4904 IPTR start_X = 0, start_Y = 0, active_X = 0, active_Y = 0, next_X = 0, next_Y = 0;
4905 IPTR x_diff = 0;
4907 #if defined(DEBUG_ILC_KEYEVENTS)
4908 D(bug("[IconList] %s: Processing key up event\n", __PRETTY_FUNCTION__));
4909 #endif
4911 switch(message->imsg->Code)
4913 case RAWKEY_RETURN:
4914 rawkey_handled = TRUE;
4916 #if defined(DEBUG_ILC_KEYEVENTS)
4917 D(bug("[IconList] %s: RAWKEY_RETURN\n", __PRETTY_FUNCTION__));
4918 #endif
4920 if (data->icld_FocusIcon) active_entry = data->icld_FocusIcon;
4921 else if (data->icld_SelectionLastClicked) active_entry = data->icld_SelectionLastClicked;
4923 if (active_entry)
4925 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
4927 active_entry->ie_Flags |= ICONENTRY_FLAG_SELECTED;
4928 AddTail(&data->icld_SelectionList, &active_entry->ie_SelectionNode);
4929 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4930 data->update_entry = active_entry;
4931 MUI_Redraw(obj, MADF_DRAWUPDATE);
4933 data->icld_SelectionLastClicked = active_entry;
4934 data->icld_FocusIcon = active_entry;
4936 SET(obj, MUIA_IconList_DoubleClick, TRUE);
4938 break;
4940 case RAWKEY_SPACE:
4941 rawkey_handled = TRUE;
4943 #if defined(DEBUG_ILC_KEYEVENTS)
4944 D(bug("[IconList] %s: RAWKEY_SPACE\n", __PRETTY_FUNCTION__));
4945 #endif
4947 if (data->icld_FocusIcon) active_entry = data->icld_FocusIcon;
4948 else if (data->icld_SelectionLastClicked) active_entry = data->icld_SelectionLastClicked;
4950 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)||(data->icld_SelectionLastClicked != active_entry)))
4952 #if defined(DEBUG_ILC_KEYEVENTS)
4953 D(bug("[IconList] %s: SPACE: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
4954 #endif
4955 DoMethod(obj, MUIM_IconList_UnselectAll);
4958 if (active_entry)
4960 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
4962 AddTail(&data->icld_SelectionList, &active_entry->ie_SelectionNode);
4963 active_entry->ie_Flags |= ICONENTRY_FLAG_SELECTED;
4964 data->icld_SelectionLastClicked = active_entry;
4966 else
4968 Remove(&active_entry->ie_SelectionNode);
4969 active_entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
4972 data->icld_FocusIcon = active_entry;
4974 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4975 data->update_entry = active_entry;
4976 MUI_Redraw(obj, MADF_DRAWUPDATE);
4978 break;
4980 case RAWKEY_PAGEUP:
4981 rawkey_handled = TRUE;
4983 #if defined(DEBUG_ILC_KEYEVENTS)
4984 D(bug("[IconList] %s: RAWKEY_PAGEUP\n", __PRETTY_FUNCTION__));
4985 #endif
4987 if (data->icld_AreaHeight > data->icld_ViewHeight)
4989 new_ViewY -= data->icld_ViewHeight;
4990 if (new_ViewY< 0)
4991 new_ViewY = 0;
4994 if (new_ViewY != data->icld_ViewY)
4996 SET(obj, MUIA_Virtgroup_Top, new_ViewY);
4998 break;
5000 case RAWKEY_PAGEDOWN:
5001 rawkey_handled = TRUE;
5003 #if defined(DEBUG_ILC_KEYEVENTS)
5004 D(bug("[IconList] %s: RAWKEY_PAGEDOWN\n", __PRETTY_FUNCTION__));
5005 #endif
5007 if (data->icld_AreaHeight > data->icld_ViewHeight)
5009 new_ViewY += data->icld_ViewHeight;
5010 if (new_ViewY > (data->icld_AreaHeight - data->icld_ViewHeight))
5011 new_ViewY = data->icld_AreaHeight - data->icld_ViewHeight;
5014 if (new_ViewY != data->icld_ViewY)
5016 SET(obj, MUIA_Virtgroup_Top, new_ViewY);
5018 break;
5020 case RAWKEY_UP:
5021 rawkey_handled = TRUE;
5023 #if defined(DEBUG_ILC_KEYEVENTS)
5024 D(bug("[IconList] %s: RAWKEY_UP\n", __PRETTY_FUNCTION__));
5025 #endif
5027 if (data->icld_FocusIcon)
5029 start_entry = data->icld_FocusIcon;
5030 #if defined(DEBUG_ILC_KEYEVENTS)
5031 D(bug("[IconList] %s: UP: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5032 #endif
5034 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5035 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5036 data->update_entry = start_entry;
5037 MUI_Redraw(obj, MADF_DRAWUPDATE);
5039 start_X = start_entry->ie_IconX;
5040 start_Y = start_entry->ie_IconY;
5041 #if defined(DEBUG_ILC_KEYEVENTS)
5042 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));
5043 #endif
5044 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5046 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5048 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5049 #if defined(DEBUG_ILC_KEYEVENTS)
5050 D(bug("[IconList] %s: UP: adjusted start_X for grid = %d\n", __PRETTY_FUNCTION__, start_X));
5051 #endif
5055 if ((active_entry = Node_PreviousVisible(start_entry)) && !(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5057 //Check if we are at the edge of the entry area ..
5058 #if defined(DEBUG_ILC_KEYEVENTS)
5059 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));
5060 #endif
5061 active_Y = active_entry->ie_IconY;
5063 if (active_Y == start_Y)
5066 #if defined(DEBUG_ILC_KEYEVENTS)
5067 D(bug("[IconList] %s: UP: active_entry is on our row (not at the edge)\n", __PRETTY_FUNCTION__));
5068 #endif
5069 entry_next = active_entry;
5070 next_X = entry_next->ie_IconX;
5071 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5073 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5074 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5078 #if defined(DEBUG_ILC_KEYEVENTS)
5079 D(bug("[IconList] %s: UP: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5080 #endif
5083 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5085 #if defined(DEBUG_ILC_KEYEVENTS)
5086 D(bug("[IconList] %s: UP: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5087 #endif
5088 DoMethod(obj, MUIM_IconList_UnselectAll);
5091 #if defined(DEBUG_ILC_KEYEVENTS)
5092 D(bug("[IconList] %s: UP: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5093 #endif
5094 if (!(active_entry))
5096 // If nothing is selected we will use the last visible entry ..
5097 active_entry = Node_LastVisible(&data->icld_IconList);
5098 start_X = active_entry->ie_IconX;
5099 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5101 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5102 start_X = start_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5104 start_Y = active_entry->ie_IconY;
5107 while (active_entry != NULL)
5109 #if defined(DEBUG_ILC_KEYEVENTS)
5110 D(bug("[IconList] %s: UP: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5111 #endif
5112 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
5114 // Return the first visible since the list flow direction matches
5115 // our cursor direction
5116 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5117 break;
5119 else
5121 active_X = active_entry->ie_IconX;
5123 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5125 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5126 x_diff = ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5128 active_Y = active_entry->ie_IconY;
5130 if (start_entry)
5132 if (entry_next)
5134 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5135 (active_Y < start_Y) &&
5136 (((active_X - x_diff) >= start_X ) &&
5137 ((active_X - x_diff) <= (start_X + start_entry->ie_AreaWidth + (x_diff*2)))))
5139 #if defined(DEBUG_ILC_KEYEVENTS)
5140 D(bug("[IconList] %s: UP: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5141 #endif
5142 break;
5144 else if (active_entry == (struct IconEntry *)GetHead(&data->icld_IconList))
5146 #if defined(DEBUG_ILC_KEYEVENTS)
5147 D(bug("[IconList] %s: UP: (A) reached list start .. restarting from the end ..\n", __PRETTY_FUNCTION__));
5148 #endif
5149 start_X = next_X;
5151 if ((entry_next = Node_PreviousVisible(entry_next)))
5153 if (entry_next->ie_IconX > start_X)
5154 entry_next = NULL;
5155 else
5157 next_X = entry_next->ie_IconX;
5158 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5160 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5161 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5165 start_Y = 0;
5166 #if defined(DEBUG_ILC_KEYEVENTS)
5167 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));
5168 #endif
5169 active_entry = Node_LastVisible(&data->icld_IconList);
5172 else
5174 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5175 (active_Y < start_Y) &&
5176 ((active_X + x_diff) < (start_X + start_entry->ie_AreaWidth + x_diff)))
5178 #if defined(DEBUG_ILC_KEYEVENTS)
5179 D(bug("[IconList] %s: UP: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5180 #endif
5181 break;
5185 else
5187 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5189 #if defined(DEBUG_ILC_KEYEVENTS)
5190 D(bug("[IconList] %s: UP: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5191 #endif
5192 break;
5196 active_entry = (struct IconEntry *)(((struct Node *)active_entry)->ln_Pred);
5199 if (!(active_entry))
5201 #if defined(DEBUG_ILC_KEYEVENTS)
5202 D(bug("[IconList] %s: UP: No Next UP Node - Getting Last visible entry ..\n", __PRETTY_FUNCTION__));
5203 #endif
5204 /* We didnt find a "next UP" entry so just use the last visible */
5205 active_entry = Node_LastVisible(&data->icld_IconList);
5208 if (active_entry)
5210 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5212 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5213 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5214 data->update_entry = active_entry;
5215 MUI_Redraw(obj, MADF_DRAWUPDATE);
5218 data->icld_FocusIcon = active_entry;
5219 break;
5221 case RAWKEY_DOWN:
5222 rawkey_handled = TRUE;
5224 #if defined(DEBUG_ILC_KEYEVENTS)
5225 D(bug("[IconList] %s: RAWKEY_DOWN\n", __PRETTY_FUNCTION__));
5226 #endif
5227 if (data->icld_FocusIcon)
5229 start_entry = data->icld_FocusIcon;
5230 #if defined(DEBUG_ILC_KEYEVENTS)
5231 D(bug("[IconList] %s: DOWN: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5232 #endif
5234 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5235 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5236 data->update_entry = start_entry;
5237 MUI_Redraw(obj, MADF_DRAWUPDATE);
5239 start_X = start_entry->ie_IconX;
5240 start_Y = start_entry->ie_IconY;
5241 #if defined(DEBUG_ILC_KEYEVENTS)
5242 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));
5243 #endif
5244 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5246 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5248 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5249 #if defined(DEBUG_ILC_KEYEVENTS)
5250 D(bug("[IconList] %s: DOWN: adjusted start_X for grid = %d\n", __PRETTY_FUNCTION__, start_X));
5251 #endif
5255 if ((active_entry = Node_NextVisible(start_entry)) &&
5256 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5258 #if defined(DEBUG_ILC_KEYEVENTS)
5259 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));
5260 #endif
5261 active_Y = active_entry->ie_IconY;
5263 if (active_Y == start_Y)
5266 #if defined(DEBUG_ILC_KEYEVENTS)
5267 D(bug("[IconList] %s: DOWN: active_entry is on our row (not at the edge)\n", __PRETTY_FUNCTION__));
5268 #endif
5269 entry_next = active_entry;
5270 next_X = entry_next->ie_IconX;
5271 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5273 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5274 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5278 #if defined(DEBUG_ILC_KEYEVENTS)
5279 D(bug("[IconList] %s: DOWN: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5280 #endif
5283 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5285 #if defined(DEBUG_ILC_KEYEVENTS)
5286 D(bug("[IconList] %s: DOWN: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5287 #endif
5288 DoMethod(obj, MUIM_IconList_UnselectAll);
5291 #if defined(DEBUG_ILC_KEYEVENTS)
5292 D(bug("[IconList] %s: DOWN: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5293 #endif
5294 if (!(active_entry))
5296 // If nothing is selected we will use the First visible entry ..
5297 active_entry = Node_FirstVisible(&data->icld_IconList);
5298 start_X = active_entry->ie_IconX;
5299 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5301 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5302 start_X = start_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5304 start_Y = active_entry->ie_IconY;
5307 while (active_entry != NULL)
5309 #if defined(DEBUG_ILC_KEYEVENTS)
5310 D(bug("[IconList] %s: DOWN: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5311 #endif
5312 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
5314 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5315 break;
5317 else
5319 active_X = active_entry->ie_IconX;
5321 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5323 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5324 x_diff = ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5326 active_Y = active_entry->ie_IconY;
5328 if (start_entry)
5330 if (entry_next)
5332 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5333 (active_Y > start_Y) &&
5334 (((active_X - x_diff) >= start_X ) &&
5335 ((active_X - x_diff) <= (start_X + start_entry->ie_AreaWidth + (x_diff*2)))))
5337 #if defined(DEBUG_ILC_KEYEVENTS)
5338 D(bug("[IconList] %s: DOWN: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5339 #endif
5340 break;
5342 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
5344 #if defined(DEBUG_ILC_KEYEVENTS)
5345 D(bug("[IconList] %s: DOWN: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
5346 #endif
5347 start_X = entry_next->ie_IconX;
5348 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5350 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5351 start_X = start_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5354 if ((entry_next = (struct IconEntry *)Node_NextVisible(entry_next)))
5356 if (entry_next->ie_IconX < start_X)
5357 entry_next = NULL;
5358 else
5360 next_X = entry_next->ie_IconX;
5361 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5363 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5364 next_X = next_X + ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5368 start_Y = 0;
5369 #if defined(DEBUG_ILC_KEYEVENTS)
5370 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));
5371 #endif
5372 active_entry = Node_FirstVisible(&data->icld_IconList);
5375 else
5377 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5378 (active_Y > start_Y) &&
5379 (active_X > start_X - 1))
5381 #if defined(DEBUG_ILC_KEYEVENTS)
5382 D(bug("[IconList] %s: DOWN: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5383 #endif
5384 break;
5388 else
5390 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5392 #if defined(DEBUG_ILC_KEYEVENTS)
5393 D(bug("[IconList] %s: DOWN: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5394 #endif
5395 break;
5399 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5402 if (!(active_entry))
5404 #if defined(DEBUG_ILC_KEYEVENTS)
5405 D(bug("[IconList] %s: DOWN: No Next DOWN Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
5406 #endif
5407 /* We didnt find a "next DOWN" entry so just use the first visible */
5408 active_entry = Node_FirstVisible(&data->icld_IconList);
5411 if (active_entry)
5413 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5415 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5416 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5417 data->update_entry = active_entry;
5418 MUI_Redraw(obj, MADF_DRAWUPDATE);
5421 data->icld_FocusIcon = active_entry;
5422 break;
5424 case RAWKEY_LEFT:
5425 rawkey_handled = TRUE;
5427 #if defined(DEBUG_ILC_KEYEVENTS)
5428 D(bug("[IconList] %s: RAWKEY_LEFT\n", __PRETTY_FUNCTION__));
5429 #endif
5430 if (data->icld_FocusIcon)
5432 start_entry = data->icld_FocusIcon;
5433 #if defined(DEBUG_ILC_KEYEVENTS)
5434 D(bug("[IconList] %s: LEFT: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5435 #endif
5437 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5438 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5439 data->update_entry = start_entry;
5440 MUI_Redraw(obj, MADF_DRAWUPDATE);
5442 start_X = start_entry->ie_IconX;
5443 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5445 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5446 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5448 start_Y = start_entry->ie_IconY;
5450 #if defined(DEBUG_ILC_KEYEVENTS)
5451 D(bug("[IconList] %s: LEFT: start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5452 #endif
5454 if (!(active_entry = Node_NextVisible(start_entry)) && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5456 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5457 #if defined(DEBUG_ILC_KEYEVENTS)
5458 D(bug("[IconList] %s: LEFT: Start at the beginning (Active @ 0x%p) using entry X + Width\n", __PRETTY_FUNCTION__, active_entry));
5459 #endif
5460 start_X = start_X + start_entry->ie_AreaWidth;
5461 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5463 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5464 start_X = start_X + ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5467 start_Y = 0;
5468 entry_next = NULL;
5470 else if (active_entry && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5472 #if defined(DEBUG_ILC_KEYEVENTS)
5473 D(bug("[IconList] %s: LEFT: Active @ 0x%p, X %d\n", __PRETTY_FUNCTION__, active_entry, active_entry->ie_IconX));
5474 #endif
5475 if ((entry_next = Node_NextVisible(start_entry)))
5477 #if defined(DEBUG_ILC_KEYEVENTS)
5478 D(bug("[IconList] %s: LEFT: Next @ 0x%p, X %d\n", __PRETTY_FUNCTION__, entry_next, entry_next->ie_IconX));
5479 #endif
5481 if (entry_next->ie_IconX < start_X)
5482 entry_next = NULL;
5483 else
5485 next_X = entry_next->ie_IconX;
5486 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5488 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5489 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5494 #if defined(DEBUG_ILC_KEYEVENTS)
5495 D(bug("[IconList] %s: LEFT: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5496 #endif
5499 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5501 #if defined(DEBUG_ILC_KEYEVENTS)
5502 D(bug("[IconList] %s: LEFT: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5503 #endif
5504 DoMethod(obj, MUIM_IconList_UnselectAll);
5507 #if defined(DEBUG_ILC_KEYEVENTS)
5508 D(bug("[IconList] %s: LEFT: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5509 #endif
5511 if (!(active_entry))
5513 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5516 while (active_entry != NULL)
5518 #if defined(DEBUG_ILC_KEYEVENTS)
5519 D(bug("[IconList] %s: LEFT: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5520 #endif
5521 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
5523 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5524 break;
5526 else
5528 LONG active_entry_X = active_entry->ie_IconX;
5529 LONG active_entry_Y;
5530 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5532 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5533 active_entry_X = active_entry_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5535 active_entry_Y = active_entry->ie_IconY;
5537 if (start_entry)
5539 if (entry_next)
5541 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5542 (active_entry_Y > start_Y) &&
5543 ((active_entry_X > start_X - 1) &&
5544 (active_entry_X < next_X)))
5546 #if defined(DEBUG_ILC_KEYEVENTS)
5547 D(bug("[IconList] %s: LEFT: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5548 #endif
5549 break;
5551 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
5553 #if defined(DEBUG_ILC_KEYEVENTS)
5554 D(bug("[IconList] %s: LEFT: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
5555 #endif
5556 start_X = entry_next->ie_IconX;
5557 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5559 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5560 start_X = start_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5563 if ((entry_next = Node_NextVisible(entry_next)))
5565 if (entry_next->ie_IconX < start_X)
5566 entry_next = NULL;
5567 else
5569 next_X = entry_next->ie_IconX;
5570 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5572 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5573 next_X = next_X + ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5577 start_Y = 0;
5578 #if defined(DEBUG_ILC_KEYEVENTS)
5579 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));
5580 #endif
5581 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5584 else
5586 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5587 (active_entry_Y > start_Y) &&
5588 (active_entry_X > start_X - 1))
5590 #if defined(DEBUG_ILC_KEYEVENTS)
5591 D(bug("[IconList] %s: LEFT: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5592 #endif
5593 break;
5597 else
5599 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5601 #if defined(DEBUG_ILC_KEYEVENTS)
5602 D(bug("[IconList] %s: LEFT: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5603 #endif
5604 break;
5608 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5611 if (!(active_entry))
5613 #if defined(DEBUG_ILC_KEYEVENTS)
5614 D(bug("[IconList] %s: LEFT: No Next LEFT Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
5615 #endif
5616 /* We didnt find a "next LEFT" entry so just use the last visible */
5617 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5618 while ((active_entry != NULL) &&(!(active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
5620 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5624 if (active_entry)
5626 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5628 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5629 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5630 data->update_entry = active_entry;
5631 MUI_Redraw(obj, MADF_DRAWUPDATE);
5634 data->icld_FocusIcon = active_entry;
5635 break;
5637 case RAWKEY_RIGHT:
5638 rawkey_handled = TRUE;
5640 #if defined(DEBUG_ILC_KEYEVENTS)
5641 D(bug("[IconList] %s: RAWKEY_RIGHT\n", __PRETTY_FUNCTION__));
5642 #endif
5644 if (data->icld_FocusIcon)
5646 start_entry = data->icld_FocusIcon;
5647 #if defined(DEBUG_ILC_KEYEVENTS)
5648 D(bug("[IconList] %s: RIGHT: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5649 #endif
5650 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5651 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5652 data->update_entry = start_entry;
5653 MUI_Redraw(obj, MADF_DRAWUPDATE);
5655 start_X = start_entry->ie_IconX;
5656 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5658 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5659 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5661 start_Y = start_entry->ie_IconY;
5663 #if defined(DEBUG_ILC_KEYEVENTS)
5664 D(bug("[IconList] %s: RIGHT: start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5665 #endif
5666 if (!(active_entry = Node_NextVisible(start_entry)) && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5668 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5669 #if defined(DEBUG_ILC_KEYEVENTS)
5670 D(bug("[IconList] %s: RIGHT: Start at the beginning (Active @ 0x%p) using entry X + Width\n", __PRETTY_FUNCTION__, active_entry));
5671 #endif
5672 start_X = 0;
5673 start_Y = start_Y + start_entry->ie_AreaHeight;
5674 entry_next = NULL;
5676 else if (active_entry && (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5678 #if defined(DEBUG_ILC_KEYEVENTS)
5679 D(bug("[IconList] %s: RIGHT: Active @ 0x%p, X %d\n", __PRETTY_FUNCTION__, active_entry, active_entry->ie_IconX));
5680 #endif
5681 if ((entry_next = Node_NextVisible(start_entry)))
5683 #if defined(DEBUG_ILC_KEYEVENTS)
5684 D(bug("[IconList] %s: RIGHT: Next @ 0x%p, X %d\n", __PRETTY_FUNCTION__, entry_next, entry_next->ie_IconX));
5685 #endif
5687 if (entry_next->ie_IconY < start_Y)
5688 entry_next = NULL;
5689 else
5690 next_Y = entry_next->ie_IconY;
5693 #if defined(DEBUG_ILC_KEYEVENTS)
5694 D(bug("[IconList] %s: RIGHT: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5695 #endif
5698 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5700 #if defined(DEBUG_ILC_KEYEVENTS)
5701 D(bug("[IconList] %s: RIGHT: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5702 #endif
5703 DoMethod(obj, MUIM_IconList_UnselectAll);
5706 #if defined(DEBUG_ILC_KEYEVENTS)
5707 D(bug("[IconList] %s: RIGHT: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5708 #endif
5710 if (!(active_entry))
5712 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5715 while (active_entry != NULL)
5717 #if defined(DEBUG_ILC_KEYEVENTS)
5718 D(bug("[IconList] %s: RIGHT: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5719 #endif
5720 if (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5722 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5723 break;
5725 else
5727 LONG active_entry_X = active_entry->ie_IconX;
5728 LONG active_entry_Y;
5729 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5731 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5732 active_entry_X = active_entry_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5734 active_entry_Y = active_entry->ie_IconY;
5736 if (start_entry)
5738 if (entry_next)
5740 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5741 (active_entry_X > start_X) &&
5742 ((active_entry_Y > start_Y - 1) &&
5743 (active_entry_Y < next_Y)))
5745 #if defined(DEBUG_ILC_KEYEVENTS)
5746 D(bug("[IconList] %s: RIGHT: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5747 #endif
5748 break;
5750 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
5752 #if defined(DEBUG_ILC_KEYEVENTS)
5753 D(bug("[IconList] %s: RIGHT: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
5754 #endif
5755 start_Y = entry_next->ie_IconY;
5757 if ((entry_next = Node_NextVisible(entry_next)))
5759 if (entry_next->ie_IconY < start_Y)
5760 entry_next = NULL;
5761 else
5763 next_Y = entry_next->ie_IconY;
5766 start_Y = 0;
5767 #if defined(DEBUG_ILC_KEYEVENTS)
5768 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));
5769 #endif
5770 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5773 else
5775 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5776 (active_entry_X > start_X) &&
5777 (active_entry_Y > start_Y - 1))
5779 #if defined(DEBUG_ILC_KEYEVENTS)
5780 D(bug("[IconList] %s: RIGHT: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5781 #endif
5782 break;
5786 else
5788 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5790 #if defined(DEBUG_ILC_KEYEVENTS)
5791 D(bug("[IconList] %s: RIGHT: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5792 #endif
5793 break;
5797 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5800 if (!(active_entry))
5802 #if defined(DEBUG_ILC_KEYEVENTS)
5803 D(bug("[IconList] %s: RIGHT: No Next RIGHT Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
5804 #endif
5805 /* We didnt find a "next RIGHT" entry so just use the first visible */
5806 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5807 while ((active_entry != NULL) &&(!(active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
5809 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5813 if (active_entry)
5815 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5817 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5818 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5819 data->update_entry = active_entry;
5820 MUI_Redraw(obj, MADF_DRAWUPDATE);
5823 data->icld_FocusIcon = active_entry;
5824 break;
5826 case RAWKEY_HOME:
5827 rawkey_handled = TRUE;
5829 #if defined(DEBUG_ILC_KEYEVENTS)
5830 D(bug("[IconList] %s: RAWKEY_HOME\n", __PRETTY_FUNCTION__));
5831 #endif
5833 if (data->icld_FocusIcon)
5835 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5836 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5837 data->update_entry = data->icld_FocusIcon;
5838 MUI_Redraw(obj, MADF_DRAWUPDATE);
5841 active_entry = Node_FirstVisible(&data->icld_IconList);
5843 if ((active_entry) && (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
5845 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5846 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5847 data->update_entry = active_entry;
5848 MUI_Redraw(obj, MADF_DRAWUPDATE);
5850 data->icld_FocusIcon = active_entry;
5851 break;
5853 case RAWKEY_END:
5854 rawkey_handled = TRUE;
5856 #if defined(DEBUG_ILC_KEYEVENTS)
5857 D(bug("[IconList] %s: RAWKEY_END\n", __PRETTY_FUNCTION__));
5858 #endif
5860 if (data->icld_FocusIcon)
5862 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5863 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5864 data->update_entry = data->icld_FocusIcon;
5865 MUI_Redraw(obj, MADF_DRAWUPDATE);
5868 active_entry = Node_LastVisible(&data->icld_IconList);
5870 if ((active_entry) && (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
5872 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5873 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5874 data->update_entry = active_entry;
5875 MUI_Redraw(obj, MADF_DRAWUPDATE);
5877 data->icld_FocusIcon = active_entry;
5878 break;
5881 if (rawkey_handled) return MUI_EventHandlerRC_Eat;
5883 break;
5885 case IDCMP_MOUSEBUTTONS:
5886 #if defined(DEBUG_ILC_EVENTS)
5887 D(bug("[IconList] %s: IDCMP_MOUSEBUTTONS\n", __PRETTY_FUNCTION__));
5888 #endif
5889 if (message->imsg->Code == SELECTDOWN)
5891 /* Check if mouse pressed on iconlist area */
5892 if (mx >= 0 && mx < _width(obj) && my >= 0 && my < _height(obj))
5894 BOOL doubleclicked = FALSE; /* both icon and empty space */
5895 struct IconEntry *node = NULL;
5896 struct IconEntry *new_selected = NULL;
5898 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
5900 /* LIST-VIEW HANDLING */
5902 LONG clickColumn = -1;
5904 LONG x = _mleft(obj) - data->icld_ViewX + LINE_SPACING_LEFT;
5905 LONG index, w, i;
5907 /* Find column in which click happened */
5908 for(i = 0; i < NUM_COLUMNS; i++)
5910 index = data->icld_LVMAttribs->lmva_ColumnPos[i];
5912 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
5914 w = data->icld_LVMAttribs->lmva_ColumnWidth[index];
5916 if ((mx >= x) && (mx < x + w))
5918 clickColumn = index;
5919 break;
5921 x += w;
5924 if (((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0) && (my <= data->icld_LVMAttribs->lmva_HeaderHeight))
5926 /* Click on header, update list */
5927 data->icld_LVMAttribs->lmva_LastSelectedColumn = clickColumn;
5929 data->icld_UpdateMode = UPDATE_HEADERENTRY;
5930 data->update_entry = (APTR)(IPTR)clickColumn;
5932 MUI_Redraw(obj, MADF_DRAWUPDATE);
5935 else
5937 LONG current = 0, index = (my - data->icld_LVMAttribs->lmva_HeaderHeight + data->icld_ViewY) / data->icld_LVMAttribs->lmva_RowHeight;
5939 /* Check if clicked on entry */
5940 ForeachNode(&data->icld_IconList, node)
5942 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5944 /* Is this node clicked? */
5945 if (current == index)
5947 new_selected = node;
5948 break;
5951 current++;
5955 /* Handle actions */
5956 IconList_HandleNewIconSelection(CLASS, obj, message, new_selected, &doubleclicked);
5959 else
5961 /* ICON-VIEW HANDLING */
5963 struct Rectangle rect;
5965 /* Check if clicked on entry */
5966 #if defined(__AROS__)
5967 ForeachNode(&data->icld_IconList, node)
5968 #else
5969 Foreach_Node(&data->icld_IconList, node);
5970 #endif
5972 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5974 /* Is this node clicked? */
5975 rect.MinX = node->ie_IconX;
5976 rect.MaxX = node->ie_IconX + node->ie_AreaWidth - 1;
5977 rect.MinY = node->ie_IconY;
5978 rect.MaxY = node->ie_IconY + node->ie_AreaHeight - 1;
5980 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
5981 (node->ie_AreaWidth < data->icld_IconAreaLargestWidth))
5983 rect.MinX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
5984 rect.MaxX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
5987 if ((((mx + data->icld_ViewX) >= rect.MinX) && ((mx + data->icld_ViewX) <= rect.MaxX )) &&
5988 (((my + data->icld_ViewY) >= rect.MinY) && ((my + data->icld_ViewY) <= rect.MaxY )))
5990 new_selected = node;
5991 #if defined(DEBUG_ILC_EVENTS)
5992 D(bug("[IconList] %s: Entry '%s' clicked on ..\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
5993 #endif
5994 break;
5999 /* Handle actions */
6000 IconList_HandleNewIconSelection(CLASS, obj, message, new_selected, &doubleclicked);
6003 if (new_selected && (new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED))
6004 data->icld_SelectionLastClicked = new_selected;
6005 else
6006 data->icld_SelectionLastClicked = NULL;
6008 data->click_x = mx;
6009 data->click_y = my;
6011 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
6013 data->icld_ClickEvent.shift = !!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT));
6014 data->icld_ClickEvent.entry = data->icld_SelectionLastClicked ? &data->icld_SelectionLastClicked->ie_IconListEntry : NULL;
6015 SET(obj, MUIA_IconList_Clicked, (IPTR)&data->icld_ClickEvent);
6017 if (doubleclicked)
6019 SET(obj, MUIA_IconList_DoubleClick, TRUE);
6022 if ((!data->mouse_pressed) &&
6023 (!doubleclicked || (doubleclicked && (data->icld_SelectionLastClicked == NULL))))
6025 data->last_secs = message->imsg->Seconds;
6026 data->last_mics = message->imsg->Micros;
6028 /* After a double click you often open a new window
6029 * and since Zune doesn't not support the faking
6030 * of SELECTUP events only change the Events
6031 * if not doubleclicked on an icon */
6033 data->mouse_pressed |= LEFT_BUTTON;
6035 /* Start listening to mouse events */
6036 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
6038 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6039 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
6040 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6044 return MUI_EventHandlerRC_Eat;
6047 else if (message->imsg->Code == MIDDLEDOWN)
6049 if (!data->mouse_pressed)
6051 data->mouse_pressed |= MIDDLE_BUTTON;
6053 data->click_x = data->icld_ViewX + mx;
6054 data->click_y = data->icld_ViewY + my;
6056 /* Start listening to mouse events */
6057 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
6059 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6060 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
6061 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6065 else
6067 if (message->imsg->Code == SELECTUP)
6069 if (data->icld_LassoActive == TRUE)
6071 #if defined(DEBUG_ILC_EVENTS) || defined(DEBUG_ILC_LASSO)
6072 D(bug("[IconList] %s: Removing Lasso\n", __PRETTY_FUNCTION__));
6073 #endif
6074 /* End Lasso-selection */
6075 struct Rectangle old_lasso;
6076 struct IconEntry *node = NULL;
6077 struct Window *thisWindow = NULL;
6079 /* Stop handling INTUITICKS */
6080 GET(obj, MUIA_Window, &thisWindow);
6081 if (thisWindow)
6083 ModifyIDCMP(thisWindow, (thisWindow->IDCMPFlags & ~(IDCMP_INTUITICKS)));
6084 if ((data->ehn.ehn_Events & IDCMP_INTUITICKS))
6086 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6087 data->ehn.ehn_Events &= ~IDCMP_INTUITICKS;
6088 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6091 /* Clear Lasso Frame.. */
6092 GetAbsoluteLassoRect(data, &old_lasso);
6093 IconList_InvertLassoOutlines(obj, data, &old_lasso);
6095 data->icld_LassoActive = FALSE;
6097 /* Remove Lasso flag from affected icons.. */
6098 #if defined(__AROS__)
6099 ForeachNode(&data->icld_IconList, node)
6100 #else
6101 Foreach_Node(&data->icld_IconList, node);
6102 #endif
6104 if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
6106 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
6109 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
6111 else if (data->icld_LVMAttribs->lmva_LastSelectedColumn != -1)
6113 ULONG orig_sortflags = data->icld_SortFlags;
6115 if (data->icld_LVMAttribs->lmva_SortColumn == data->icld_LVMAttribs->lmva_LastSelectedColumn)
6117 if (data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
6118 data->icld_SortFlags &= ~MUIV_IconList_Sort_Reverse;
6119 else
6120 data->icld_SortFlags |= MUIV_IconList_Sort_Reverse;
6123 switch (data->icld_LVMAttribs->lmva_LastSelectedColumn)
6125 case INDEX_NAME:
6126 data->icld_SortFlags &= ~MUIV_IconList_Sort_Orders;
6127 data->icld_SortFlags |= MUIV_IconList_Sort_ByName;
6128 break;
6130 case INDEX_SIZE:
6131 data->icld_SortFlags &= ~MUIV_IconList_Sort_Orders;
6132 data->icld_SortFlags |= MUIV_IconList_Sort_BySize;
6133 break;
6135 case INDEX_LASTACCESS:
6136 data->icld_SortFlags &= ~MUIV_IconList_Sort_Orders;
6137 data->icld_SortFlags |= MUIV_IconList_Sort_ByDate;
6138 break;
6141 if (orig_sortflags != data->icld_SortFlags)
6143 data->icld_LVMAttribs->lmva_SortColumn = data->icld_LVMAttribs->lmva_LastSelectedColumn;
6145 data->icld_LVMAttribs->lmva_LastSelectedColumn = -1;
6147 DoMethod(obj, MUIM_IconList_Sort);
6151 data->mouse_pressed &= ~LEFT_BUTTON;
6154 if (message->imsg->Code == MIDDLEUP)
6156 data->mouse_pressed &= ~MIDDLE_BUTTON;
6159 /* Stop listening to mouse move events is no buttons pressed */
6160 if ((data->ehn.ehn_Events & IDCMP_MOUSEMOVE) && !data->mouse_pressed)
6162 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6163 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
6164 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6167 break;
6169 case IDCMP_INTUITICKS:
6171 #if defined(DEBUG_ILC_EVENTS)
6172 D(bug("[IconList] %s: IDCMP_INTUITICKS (%d, %d)\n", __PRETTY_FUNCTION__, mx, my));
6173 #endif
6174 if ((data->icld_LassoActive == FALSE)||(!(data->mouse_pressed & LEFT_BUTTON)))
6176 break;
6178 if (((mx >= 0) && (mx <= _mwidth(obj))) &&
6179 ((my >= 0) && (my <= _mheight(obj))))
6180 break;
6183 case IDCMP_MOUSEMOVE:
6184 #if defined(DEBUG_ILC_EVENTS)
6185 D(bug("[IconList] %s: IDCMP_MOUSEMOVE\n", __PRETTY_FUNCTION__));
6186 #endif
6187 if (data->mouse_pressed & LEFT_BUTTON)
6189 LONG move_x = mx;
6190 LONG move_y = my;
6192 if (data->icld_SelectionLastClicked && (data->icld_LassoActive == FALSE) &&
6193 ((abs(move_x - data->click_x) >= 2) || (abs(move_y - data->click_y) >= 2)))
6195 LONG touch_x, touch_y;
6197 /* Entry(s) being dragged .... */
6198 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6199 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
6200 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6202 data->mouse_pressed &= ~LEFT_BUTTON;
6204 /* Pass view relative coords */
6205 touch_x = move_x + data->icld_ViewX;
6206 touch_y = move_y + data->icld_ViewY;
6207 DoMethod(obj,MUIM_DoDrag, touch_x, touch_y, 0);
6209 else if (data->icld_LassoActive == TRUE)
6211 #if defined(DEBUG_ILC_EVENTS) || defined(DEBUG_ILC_LASSO)
6212 D(bug("[IconList] %s: Update Lasso\n", __PRETTY_FUNCTION__));
6213 #endif
6214 /* Lasso active */
6215 struct Rectangle new_lasso,
6216 old_lasso;
6217 struct Rectangle iconrect;
6219 struct IconEntry *node = NULL;
6220 // struct IconEntry *new_selected = NULL;
6222 /* Remove previous Lasso frame */
6223 GetAbsoluteLassoRect(data, &old_lasso);
6224 IconList_InvertLassoOutlines(obj, data, &old_lasso);
6226 /* if the mouse leaves our visible area scroll the view */
6227 if (mx < 0 || mx >= _mwidth(obj) || my < 0 || my >= _mheight(obj))
6229 LONG newleft = data->icld_ViewX;
6230 LONG newtop = data->icld_ViewY;
6232 if (mx >= _mwidth(obj)) newleft += (mx - _mwidth(obj));
6233 else if (mx < 0) newleft += mx;
6234 if (my >= _mheight(obj)) newtop += (my - _mheight(obj));
6235 else if (my < 0) newtop += my;
6237 if (newleft + _mwidth(obj) > data->icld_AreaWidth) newleft = data->icld_AreaWidth - _mwidth(obj);
6238 if (newleft < 0) newleft = 0;
6240 if (newtop + _mheight(obj) > data->icld_AreaHeight) newtop = data->icld_AreaHeight - _mheight(obj);
6241 if (newtop < 0) newtop = 0;
6243 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
6245 SetAttrs(obj, MUIA_Virtgroup_Left, newleft, MUIA_Virtgroup_Top, newtop, TAG_DONE);
6249 /* update Lasso coordinates */
6250 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
6251 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
6253 /* get absolute Lasso coordinates */
6254 GetAbsoluteLassoRect(data, &new_lasso);
6256 LONG current = 0, startIndex = 0, endIndex = 0;
6258 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6260 LONG minY = data->icld_LassoRectangle.MinY,
6261 maxY = data->icld_LassoRectangle.MaxY;
6263 if (minY > maxY)
6265 minY ^= maxY;
6266 maxY ^= minY;
6267 minY ^= maxY;
6270 startIndex = ((minY + 1) - data->icld_LVMAttribs->lmva_HeaderHeight) / data->icld_LVMAttribs->lmva_RowHeight;
6271 endIndex = ((maxY - 1) - data->icld_LVMAttribs->lmva_HeaderHeight) / data->icld_LVMAttribs->lmva_RowHeight;
6274 #if defined(__AROS__)
6275 ForeachNode(&data->icld_IconList, node)
6276 #else
6277 Foreach_Node(&data->icld_IconList, node);
6278 #endif
6280 IPTR update_entry = (IPTR)NULL;
6282 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6284 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6286 update_entry = FALSE;
6288 if ((current >= startIndex) && (current <= endIndex))
6290 //Entry is inside our lasso ..
6291 if (!(node->ie_Flags & ICONENTRY_FLAG_LASSO))
6293 /* check if entry was already selected before */
6294 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6296 Remove(&node->ie_SelectionNode);
6297 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6299 else
6301 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6302 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6304 node->ie_Flags |= ICONENTRY_FLAG_LASSO;
6305 update_entry = (IPTR)node;
6308 else if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
6310 //Entry is no longer inside our lasso - revert its selected state
6311 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6313 Remove(&node->ie_SelectionNode);
6314 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6316 else
6318 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6319 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6321 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
6322 update_entry = (IPTR)node;
6325 current++;
6328 else
6330 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6332 iconrect.MinX = node->ie_IconX;
6333 iconrect.MaxX = node->ie_IconX + node->ie_AreaWidth - 1;
6334 iconrect.MinY = node->ie_IconY;
6335 iconrect.MaxY = node->ie_IconY + node->ie_AreaHeight - 1;
6336 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
6337 (node->ie_AreaWidth < data->icld_IconAreaLargestWidth))
6339 iconrect.MinX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
6340 iconrect.MaxX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
6343 if ((((new_lasso.MaxX + data->icld_ViewX) >= iconrect.MinX) && ((new_lasso.MinX + data->icld_ViewX) <= iconrect.MaxX)) &&
6344 (((new_lasso.MaxY + data->icld_ViewY) >= iconrect.MinY) && ((new_lasso.MinY + data->icld_ViewY) <= iconrect.MaxY)))
6346 //Entry is inside our lasso ..
6347 if (!(node->ie_Flags & ICONENTRY_FLAG_LASSO))
6349 /* check if entry was already selected before */
6350 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6352 Remove(&node->ie_SelectionNode);
6353 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6355 else
6357 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6358 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6360 node->ie_Flags |= ICONENTRY_FLAG_LASSO;
6361 update_entry = (IPTR)node;
6364 else if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
6366 //Entry is no longer inside our lasso - revert its selected state
6367 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6369 Remove(&node->ie_SelectionNode);
6370 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6372 else
6374 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6375 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6377 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
6378 update_entry = (IPTR)node;
6382 if (update_entry)
6384 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
6385 data->update_entry = (struct IconEntry *)update_entry;
6386 MUI_Redraw(obj, MADF_DRAWUPDATE);
6389 /* Draw Lasso frame */
6390 IconList_InvertLassoOutlines(obj, data, &new_lasso);
6393 return MUI_EventHandlerRC_Eat;
6395 else if (data->mouse_pressed & MIDDLE_BUTTON)
6397 /* Content is being scrolled */
6398 LONG newleft, newtop;
6400 newleft = data->click_x - mx;
6401 newtop = data->click_y - my;
6403 if (newleft + _mwidth(obj) > data->icld_AreaWidth) newleft = data->icld_AreaWidth - _mwidth(obj);
6404 if (newleft < 0) newleft = 0;
6406 if (newtop + _mheight(obj) > data->icld_AreaHeight) newtop = data->icld_AreaHeight - _mheight(obj);
6407 if (newtop < 0) newtop = 0;
6409 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
6411 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
6412 MUIA_Virtgroup_Top, newtop,
6413 TAG_DONE);
6416 return MUI_EventHandlerRC_Eat;
6419 break;
6423 return 0;
6427 ///MUIM_IconList_NextIcon()
6428 /**************************************************************************
6429 MUIM_IconList_NextIcon
6430 **************************************************************************/
6431 IPTR IconList__MUIM_IconList_NextIcon(struct IClass *CLASS, Object *obj, struct MUIP_IconList_NextIcon *message)
6433 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6434 struct IconEntry *node = NULL;
6435 struct IconList_Entry *ent = NULL;
6436 IPTR node_successor = (IPTR)NULL;
6438 if (message->entry == NULL) return (IPTR)NULL;
6439 ent = *message->entry;
6441 #if defined(DEBUG_ILC_FUNCS)
6442 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6443 #endif
6445 if ((IPTR)ent == (IPTR)MUIV_IconList_NextIcon_Start)
6447 D(bug("[IconList] %s: Finding First Entry ..\n", __PRETTY_FUNCTION__));
6448 if (message->nextflag == MUIV_IconList_NextIcon_Selected)
6450 node = (struct IconEntry *)GetHead(&data->icld_SelectionList);
6451 if (node != NULL)
6453 node = (struct IconEntry *)((IPTR)node - ((IPTR)&node->ie_SelectionNode - (IPTR)node));
6456 else if (message->nextflag == MUIV_IconList_NextIcon_Visible)
6458 node = (struct IconEntry *)GetHead(&data->icld_IconList);
6459 while (node != NULL)
6461 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6462 break;
6464 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6468 else if ((IPTR)ent != (IPTR)MUIV_IconList_NextIcon_End)
6470 node = (struct IconEntry *)((IPTR)ent - ((IPTR)&node->ie_IconListEntry - (IPTR)node));
6471 if (message->nextflag == MUIV_IconList_NextIcon_Selected)
6473 node_successor = (IPTR)GetSucc(&node->ie_SelectionNode);
6474 if (node_successor != (IPTR)NULL)
6475 node = (struct IconEntry *)((IPTR)node_successor - ((IPTR)&node->ie_SelectionNode - (IPTR)node));
6476 else
6478 D(bug("[IconList] %s: GetSucc() == NULL\n", __PRETTY_FUNCTION__));
6479 node = NULL;
6482 else if (message->nextflag == MUIV_IconList_NextIcon_Visible)
6484 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6485 while (node != NULL)
6487 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6488 break;
6490 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6495 if (node == NULL)
6497 D(bug("[IconList] %s: Returning MUIV_IconList_NextIcon_End\n", __PRETTY_FUNCTION__));
6499 *message->entry = (struct IconList_Entry *)MUIV_IconList_NextIcon_End;
6501 else
6503 D(bug("[IconList] %s: Returning entry for '%s'\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
6505 *message->entry = &node->ie_IconListEntry;
6508 return (IPTR)NULL;
6512 ///MUIM_IconList_GetIconPrivate()
6513 /**************************************************************************
6514 MUIM_IconList_GetIconPrivate
6515 **************************************************************************/
6516 IPTR IconList__MUIM_IconList_GetIconPrivate(struct IClass *CLASS, Object *obj, struct MUIP_IconList_GetIconPrivate *message)
6518 // struct IconList_DATA *data = INST_DATA(CLASS, obj);
6519 struct IconEntry *node = NULL;
6521 if (message->entry == NULL) return (IPTR)NULL;
6523 node = (struct IconEntry *)((IPTR)message->entry - ((IPTR)&node->ie_IconListEntry - (IPTR)node));
6525 return (IPTR)node;
6528 ///MUIM_CreateDragImage()
6529 /**************************************************************************
6530 MUIM_CreateDragImage
6531 **************************************************************************/
6532 IPTR IconList__MUIM_CreateDragImage(struct IClass *CLASS, Object *obj, struct MUIP_CreateDragImage *message)
6534 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6535 struct MUI_DragImage *img = NULL;
6536 LONG first_x = -1,
6537 first_y = -1;
6538 BOOL transp = XGET(obj, MUIA_IconList_DragImageTransparent);
6540 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6541 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6542 #endif
6544 if (!(data->icld_SelectionLastClicked))
6545 DoSuperMethodA(CLASS, obj, (Msg)message);
6547 if ((img = (struct MUI_DragImage *)AllocVec(sizeof(struct MUIP_CreateDragImage), MEMF_CLEAR)))
6549 struct Node *node = NULL;
6550 struct IconEntry *entry = NULL;
6552 #if defined(CREATE_FULL_DRAGIMAGE)
6553 #if defined(__AROS__)
6554 ForeachNode(&data->icld_SelectionList, node)
6555 #else
6556 Foreach_Node(&data->icld_SelectionList, node);
6557 #endif
6559 entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
6560 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) && (entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
6562 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) != ICONLIST_DISP_MODELIST)
6564 if ((first_x == -1) || ((first_x != -1) && (entry->ie_IconX < first_x))) first_x = entry->ie_IconX;
6565 if ((first_y == -1) || ((first_y != -1) && (entry->ie_IconY < first_y))) first_y = entry->ie_IconY;
6567 if (data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH)
6569 if ((entry->ie_IconX + entry->ie_AreaWidth) > img->width) img->width = entry->ie_IconX + entry->ie_AreaWidth;
6570 if ((entry->ie_IconY + entry->ie_AreaHeight) > img->height) img->height = entry->ie_IconY + entry->ie_AreaHeight;
6573 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
6575 if ((entry->ie_IconX + data->icld_IconAreaLargestWidth) > img->width) img->width = entry->ie_IconX + data->icld_IconAreaLargestWidth;
6576 if ((entry->ie_IconY + data->icld_IconAreaLargestHeight) > img->height) img->height = entry->ie_IconY + data->icld_IconAreaLargestHeight;
6579 else
6581 img->height += data->icld_LVMAttribs->lmva_RowHeight;
6585 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6587 first_x = 0;
6588 first_y = -message->touchy;
6589 img->width = data->icld_LVMAttribs->lmva_ColumnWidth[data->icld_LVMAttribs->lmva_ColumnPos[INDEX_TYPE]] +
6590 data->icld_LVMAttribs->lmva_ColumnWidth[data->icld_LVMAttribs->lmva_ColumnPos[INDEX_NAME]];
6591 img->height += 2;
6593 else
6595 img->width = (img->width - first_x) + 2;
6596 img->height = (img->height - first_y) + 2;
6598 #else
6599 entry = data->icld_SelectionLastClicked;
6600 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6602 img->width = _mright(obj) - _mleft(obj);
6603 img->height = data->icld_LVMAttribs->lmva_RowHeight;
6604 first_x = 0;
6605 first_y = 0;
6607 else
6609 img->width = entry->ie_IconWidth;
6610 img->height = entry->ie_IconHeight;
6611 first_x = entry->ie_IconX;
6612 first_y = entry->ie_IconY;
6614 #endif
6616 if (transp)
6618 /* Request 32-bit, because the image will have alpha channel */
6619 img->bm = AllocBitMap(img->width, img->height, 32, BMF_CLEAR, NULL);
6621 else
6623 LONG depth = GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH);
6624 img->bm = AllocBitMap(img->width, img->height, depth, BMF_CLEAR, _screen(obj)->RastPort.BitMap);
6627 if (img->bm)
6629 struct RastPort temprp;
6630 InitRastPort(&temprp);
6631 temprp.BitMap = img->bm;
6632 ULONG minY = 0;
6634 #if defined(CREATE_FULL_DRAGIMAGE)
6635 ForeachNode(&data->icld_SelectionList, node)
6637 entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
6638 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) && (entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
6640 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6642 struct Rectangle field_rect;
6643 ULONG selected = entry->ie_Flags & ICONENTRY_FLAG_SELECTED;
6644 entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED; /* Drawing as not selected actually looks better */
6646 field_rect.MinX = 0; field_rect.MaxX = img->width - 1;
6647 field_rect.MinY = minY; field_rect.MaxY = field_rect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
6648 RenderEntryField(obj, data, entry, &field_rect, INDEX_TYPE, TRUE, FALSE, &temprp);
6650 field_rect.MinX = data->icld_LVMAttribs->lmva_ColumnWidth[data->icld_LVMAttribs->lmva_ColumnPos[INDEX_TYPE]] - 1;
6651 field_rect.MaxX = img->width - 1;
6652 field_rect.MinY = minY; field_rect.MaxY = field_rect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
6653 RenderEntryField(obj, data, entry, &field_rect, INDEX_NAME, FALSE, FALSE, &temprp);
6655 minY += data->icld_LVMAttribs->lmva_RowHeight;
6657 entry->ie_Flags |= selected;
6659 else
6661 LONG offsetx , offsety;
6663 IconList_GetIconImageOffsets(data, entry, &offsetx, &offsety);
6665 DrawIconStateA
6667 &temprp, entry->ie_DiskObj, NULL,
6668 (entry->ie_IconX + 1) - first_x + offsetx, (entry->ie_IconY + 1) - first_y + offsety,
6669 IDS_SELECTED,
6670 __iconList_DrawIconStateTags
6675 #else
6676 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6678 SetABPenDrMd(&temprp, _pens(obj)[MPEN_SHINE], 0, JAM1);
6679 RectFill(&temprp, 0, 0, img->width, img->height);
6681 else
6683 DrawIconStateA
6685 &temprp, entry->ie_DiskObj, NULL,
6686 0, 0,
6687 IDS_SELECTED,
6688 __iconList_DrawIconStateTags
6691 #endif
6692 if (transp)
6693 RastPortSetAlpha(&temprp, data->click_x, data->click_y, img->width, img->height, 0xC0, RPALPHAFLAT);
6694 DeinitRastPort(&temprp);
6697 /* Convert view relative coords to drag image relative. This is done because the "object" that is being
6698 * dragged is virtual (its a collection of icons) and the coords passed to DoDrag are not relative to this
6699 * "object"
6701 img->touchx = first_x + message->touchx;
6702 img->touchy = first_y + message->touchy;
6704 if (transp)
6705 img->flags = MUIF_DRAGIMAGE_SOURCEALPHA;
6706 else
6707 img->flags = 0;
6709 return (IPTR)img;
6713 ///MUIM_DeleteDragImage()
6714 /**************************************************************************
6715 MUIM_DeleteDragImage
6716 **************************************************************************/
6717 IPTR IconList__MUIM_DeleteDragImage(struct IClass *CLASS, Object *obj, struct MUIP_DeleteDragImage *message)
6719 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6721 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6722 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6723 #endif
6725 if (!(data->icld_SelectionLastClicked)) return DoSuperMethodA(CLASS,obj,(Msg)message);
6727 if (message->di)
6729 if (message->di->bm)
6730 FreeBitMap(message->di->bm);
6731 FreeVec(message->di);
6733 return (IPTR)NULL;
6737 ///MUIM_DragQuery()
6738 /**************************************************************************
6739 MUIM_DragQuery
6740 **************************************************************************/
6741 IPTR IconList__MUIM_DragQuery(struct IClass *CLASS, Object *obj, struct MUIP_DragQuery *message)
6743 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6744 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6745 #endif
6747 /* TODO: highlight the possible drop target entry .. */
6749 if (message->obj == obj)
6750 return MUIV_DragQuery_Accept;
6751 else
6753 BOOL is_iconlist = FALSE;
6754 struct IClass *msg_cl = OCLASS(message->obj);
6756 while (msg_cl)
6758 if (msg_cl == CLASS)
6760 is_iconlist = TRUE;
6761 break;
6763 msg_cl = msg_cl->cl_Super;
6765 if (is_iconlist)
6766 return MUIV_DragQuery_Accept;
6769 return MUIV_DragQuery_Refuse;
6773 ///MUIM_DragDrop()
6774 /**************************************************************************
6775 MUIM_DragDrop
6776 **************************************************************************/
6777 IPTR IconList__MUIM_DragDrop(struct IClass *CLASS, Object *obj, struct MUIP_DragDrop *message)
6779 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6781 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6782 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6783 #endif
6785 struct IconList_Entry *entry = (IPTR)MUIV_IconList_NextIcon_Start;
6787 if (data->icld_DragDropEvent)
6789 struct IconList_Drop_SourceEntry *clean_node;
6790 #if defined(DEBUG_ILC_ICONDRAGDROP)
6791 D(bug("[IconList] %s: Cleaning existing IconList_Drop_Event @ %p\n", __PRETTY_FUNCTION__, data->icld_DragDropEvent));
6792 #endif
6793 while ((clean_node = (struct IconList_Drop_SourceEntry *)RemTail(&data->icld_DragDropEvent->drop_SourceList)) != NULL)
6795 FreeVec(clean_node->dropse_Node.ln_Name);
6796 FreeMem(clean_node, sizeof(struct IconList_Drop_SourceEntry));
6798 FreeVec(data->icld_DragDropEvent->drop_TargetPath);
6799 FreeMem(data->icld_DragDropEvent, sizeof(struct IconList_Drop_Event));
6800 data->icld_DragDropEvent = NULL;
6803 /* SANITY CHECK: Get first selected entry from SOURCE iconlist */
6804 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
6806 if ((entry) && ((IPTR)entry != MUIV_IconList_NextIcon_End))
6808 /* Ok.. atleast one entry was dropped .. */
6809 char tmp_dirbuff[256];
6810 BPTR tmp_dirlock = (BPTR) NULL;
6812 BOOL iconMove = FALSE;
6813 struct IconEntry *node = NULL;
6814 struct IconEntry *drop_target_node = NULL;
6815 STRPTR directory_path = NULL;
6816 struct IconList_Drop_Event *dragDropEvent = NULL;
6818 GET(obj, MUIA_IconDrawerList_Drawer, &directory_path);
6820 /* Properly expand the name incase it uses devices rather than volumes */
6821 if (directory_path != NULL)
6823 tmp_dirlock = Lock(directory_path, SHARED_LOCK);
6824 if (tmp_dirlock)
6826 if (NameFromLock(tmp_dirlock, tmp_dirbuff, 256) != 0)
6828 directory_path = tmp_dirbuff;
6830 UnLock(tmp_dirlock);
6833 if ((dragDropEvent = AllocMem(sizeof(struct IconList_Drop_Event), MEMF_CLEAR)) == NULL)
6835 #if defined(DEBUG_ILC_ICONDRAGDROP)
6836 D(bug("[IconList] %s: Failed to allocate IconList_Drop_Event Storage!\n", __PRETTY_FUNCTION__));
6837 #endif
6838 goto dragdropdone;
6840 #if defined(DEBUG_ILC_ICONDRAGDROP)
6841 D(bug("[IconList] %s: Allocated IconList_Drop_Event @ %p\n", __PRETTY_FUNCTION__, dragDropEvent));
6842 #endif
6844 NewList(&dragDropEvent->drop_SourceList);
6846 /* go through list and check if dropped on entry */
6847 int rowCount = 0;
6849 #if defined(__AROS__)
6850 ForeachNode(&data->icld_IconList, node)
6851 #else
6852 Foreach_Node(&data->icld_IconList, node);
6853 #endif
6855 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6857 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6859 ULONG rowTop = _mtop(obj) + (rowCount * data->icld_LVMAttribs->lmva_RowHeight);
6860 rowTop += data->icld_LVMAttribs->lmva_HeaderHeight;
6862 if (((message->x > _mleft(obj)) && (message->x < _mright(obj)))
6863 && ((message->y > rowTop) && (message->y < (rowTop + data->icld_LVMAttribs->lmva_RowHeight))))
6865 drop_target_node = node;
6866 break;
6869 rowCount++;
6872 else
6874 struct Rectangle iconbox;
6875 LONG click_x = message->x - _mleft(obj);
6876 LONG click_y = message->y - _mtop(obj);
6877 iconbox.MinX = node->ie_IconX - data->icld_ViewX;
6878 iconbox.MaxX = (node->ie_IconX + node->ie_AreaWidth) - data->icld_ViewX;
6879 iconbox.MinY = node->ie_IconY - data->icld_ViewY;
6880 iconbox.MaxY = (node->ie_IconY + node->ie_AreaHeight)- data->icld_ViewY;
6882 if ((node->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
6883 (click_x >= iconbox.MinX) &&
6884 (click_x < iconbox.MaxX) &&
6885 (click_y >= iconbox.MinY) &&
6886 (click_y < iconbox.MaxY))
6888 drop_target_node = node;
6889 break;
6894 /* Additional filter - if same window and the target entry is selected (==dragged), then it was intended as a move */
6895 if ((message->obj == obj) && (drop_target_node) && (drop_target_node->ie_Flags & ICONENTRY_FLAG_SELECTED))
6896 drop_target_node = NULL;
6898 if ((drop_target_node != NULL) &&
6899 ((drop_target_node->ie_IconListEntry.type == ST_SOFTLINK) ||
6900 (drop_target_node->ie_IconListEntry.type == ST_ROOT) ||
6901 (drop_target_node->ie_IconListEntry.type == ST_USERDIR) ||
6902 (drop_target_node->ie_IconListEntry.type == ST_LINKDIR) ||
6903 (drop_target_node->ie_IconListEntry.type == ST_FILE) ||
6904 (drop_target_node->ie_IconListEntry.type == ST_LINKFILE)))
6906 /* Dropped on some entry */
6907 if ((drop_target_node->ie_IconListEntry.type != ST_ROOT) && (drop_target_node->ie_IconListEntry.type != ST_SOFTLINK))
6909 if (directory_path)
6911 int fulllen = strlen(directory_path) + strlen(drop_target_node->ie_IconListEntry.label) + 2;
6913 if ((dragDropEvent->drop_TargetPath = AllocVec(fulllen, MEMF_CLEAR)) == NULL)
6915 bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__);
6916 goto dragdropdone;
6918 strcpy(dragDropEvent->drop_TargetPath, directory_path);
6919 AddPart(dragDropEvent->drop_TargetPath, drop_target_node->ie_IconListEntry.label, fulllen);
6921 else
6922 goto dragdropdone;
6924 else
6926 if ((dragDropEvent->drop_TargetPath = AllocVec(strlen(drop_target_node->ie_IconListEntry.label) + 1, MEMF_CLEAR)) == NULL)
6928 bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__);
6929 goto dragdropdone;
6931 strcpy(dragDropEvent->drop_TargetPath, drop_target_node->ie_IconListEntry.label);
6934 #if defined(DEBUG_ILC_ICONDRAGDROP)
6935 D(bug("[IconList] %s: Target Entry Full Path = '%s'\n", __PRETTY_FUNCTION__, dragDropEvent->drop_TargetPath));
6936 #endif
6937 /* mark the Entry the selection was dropped on*/
6938 //drop_target_node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6939 //data->icld_UpdateMode = UPDATE_SINGLEENTRY;
6940 //data->update_entry = drop_target_node;
6941 //MUI_Redraw(obj,MADF_DRAWUPDATE);
6943 else
6945 /* Not dropped on entry -> get path of DESTINATION iconlist */
6946 /* Note: directory_path is NULL when dropped on Wanderer's desktop */
6947 if ((message->obj != obj) && directory_path)
6949 #if defined(DEBUG_ILC_ICONDRAGDROP)
6950 D(bug("[IconList] %s: drop entry: Icons dropped in window '%s'\n", __PRETTY_FUNCTION__, directory_path));
6951 #endif
6952 /* copy path */
6953 if ((dragDropEvent->drop_TargetPath = AllocVec(strlen(directory_path) + 1, MEMF_CLEAR)) != NULL)
6955 strcpy(dragDropEvent->drop_TargetPath, directory_path);
6957 else
6959 #if defined(DEBUG_ILC_ICONDRAGDROP)
6960 D(bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__));
6961 #endif
6962 goto dragdropdone;
6965 else if (message->obj == obj)
6967 #if defined(DEBUG_ILC_ICONDRAGDROP)
6968 D(bug("[IconList] %s: drop entry: Entry Move detected ..\n", __PRETTY_FUNCTION__));
6969 #endif
6970 iconMove = TRUE;
6972 /* Adjust entry posiions .. */
6973 #if defined(DEBUG_ILC_ICONDRAGDROP)
6974 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));
6975 #endif
6976 LONG offset_x = message->x - (data->click_x + _mleft(obj));
6977 LONG offset_y = message->y - (data->click_y + _mtop(obj));
6979 entry = (IPTR)MUIV_IconList_NextIcon_Start;
6980 while ((IPTR)entry != MUIV_IconList_NextIcon_End)
6982 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
6984 if ((IPTR)entry != MUIV_IconList_NextIcon_End)
6986 entry->ile_IconEntry->ie_IconX += offset_x;
6987 entry->ile_IconEntry->ie_IconY += offset_y;
6988 /* Remember new position as provided */
6989 DoMethod(obj, MUIM_IconList_PropagateEntryPos, entry->ile_IconEntry);
6991 SET(obj, MUIA_IconList_IconMoved, (IPTR)entry); // Now notify
6993 MUI_Redraw(obj,MADF_DRAWOBJECT);
6994 DoMethod(obj, MUIM_IconList_CoordsSort);
6996 else
6998 #if defined(DEBUG_ILC_ICONDRAGDROP)
6999 D(bug("[IconList] %s: Icons Dropped on Wanderer Desktop (unhandled)!\n", __PRETTY_FUNCTION__));
7000 #endif
7001 iconMove = TRUE;
7006 if (!(iconMove))
7008 int copycount = 0;
7009 /* Create list of entries to copy .. */
7010 entry = (IPTR)MUIV_IconList_NextIcon_Start;
7011 while ((IPTR)entry != MUIV_IconList_NextIcon_End)
7013 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
7015 if ((IPTR)entry != MUIV_IconList_NextIcon_End)
7017 struct IconList_Drop_SourceEntry *sourceEntry = NULL;
7018 sourceEntry = AllocMem(sizeof(struct IconList_Drop_SourceEntry), MEMF_CLEAR);
7019 if ((entry->type != ST_ROOT) && (entry->type != ST_SOFTLINK))
7021 int fulllen = 0;
7022 char *path = NULL;
7024 GET(message->obj, MUIA_IconDrawerList_Drawer, &path);
7025 /* Properly expand the location in case it uses devices rather than volumes */
7026 if (path != NULL)
7028 tmp_dirlock = Lock(path, SHARED_LOCK);
7029 if (tmp_dirlock)
7031 if (NameFromLock(tmp_dirlock, tmp_dirbuff, 256))
7033 path = tmp_dirbuff;
7035 UnLock(tmp_dirlock);
7038 if (strcasecmp(dragDropEvent->drop_TargetPath, path) != 0)
7040 fulllen = strlen(path) + strlen(entry->ile_IconEntry->ie_IconNode.ln_Name) + 2;
7041 sourceEntry->dropse_Node.ln_Name = AllocVec(fulllen, MEMF_CLEAR);
7042 if (sourceEntry->dropse_Node.ln_Name != NULL)
7044 strcpy(sourceEntry->dropse_Node.ln_Name, path);
7045 AddPart(sourceEntry->dropse_Node.ln_Name, entry->label, fulllen);
7047 #if defined(DEBUG_ILC_ICONDRAGDROP)
7048 D(bug("[IconList] %s: Source Entry (Full Path) = '%s'\n", __PRETTY_FUNCTION__, sourceEntry->dropse_Node.ln_Name));
7049 #endif
7053 else
7055 sourceEntry->dropse_Node.ln_Name = AllocVec(strlen(entry->label) + 1, MEMF_CLEAR);
7056 if (sourceEntry->dropse_Node.ln_Name != NULL)
7057 strcpy(sourceEntry->dropse_Node.ln_Name, entry->label);
7058 #if defined(DEBUG_ILC_ICONDRAGDROP)
7059 D(bug("[IconList] %s: Source Entry = '%s'\n", __PRETTY_FUNCTION__, sourceEntry->dropse_Node.ln_Name));
7060 #endif
7063 if ((sourceEntry->dropse_Node.ln_Name != NULL) && (strcasecmp(dragDropEvent->drop_TargetPath, sourceEntry->dropse_Node.ln_Name) != 0))
7065 copycount += 1;
7066 AddTail(&dragDropEvent->drop_SourceList, &sourceEntry->dropse_Node);
7068 else
7070 #if defined(DEBUG_ILC_ICONDRAGDROP)
7071 D(bug("[IconList] %s: Source == Dest, Skipping!\n", __PRETTY_FUNCTION__));
7072 #endif
7073 FreeVec(sourceEntry->dropse_Node.ln_Name);
7074 FreeMem(sourceEntry, sizeof(struct IconList_Drop_SourceEntry));
7078 if (copycount > 0)
7080 dragDropEvent->drop_TargetObj = obj;
7082 #if defined(DEBUG_ILC_ICONDRAGDROP)
7083 D(bug("[IconList] %s: Causing DROP notification..\n", __PRETTY_FUNCTION__));
7084 #endif
7085 SET(obj, MUIA_IconList_IconsDropped, (IPTR)dragDropEvent);
7086 DoMethod(obj, MUIM_IconList_CoordsSort);
7088 else
7090 FreeVec(dragDropEvent->drop_TargetPath);
7091 FreeMem(dragDropEvent, sizeof(struct IconList_Drop_Event));
7095 else
7097 #if defined(DEBUG_ILC_ICONDRAGDROP)
7098 D(bug("[IconList] %s: BUG - DragDrop received with no source icons!\n", __PRETTY_FUNCTION__));
7099 #endif
7100 NNSET(obj, MUIA_IconList_IconsDropped, (IPTR)NULL);
7103 dragdropdone:
7104 return DoSuperMethodA(CLASS, obj, (Msg)message);
7108 ///MUIM_UnselectAll()
7109 /**************************************************************************
7110 MUIM_UnselectAll
7111 **************************************************************************/
7112 IPTR IconList__MUIM_IconList_UnselectAll(struct IClass *CLASS, Object *obj, Msg message)
7114 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7115 struct Node *node = NULL, *next_node = NULL;
7116 BOOL changed = FALSE;
7118 #if defined(DEBUG_ILC_FUNCS)
7119 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7120 #endif
7122 data->icld_SelectionLastClicked = NULL;
7123 data->icld_FocusIcon = NULL;
7124 #if defined(__AROS__)
7125 ForeachNodeSafe(&data->icld_SelectionList, node, next_node)
7126 #else
7127 Foreach_NodeSafe(&data->icld_SelectionList, node, next_node);
7128 #endif
7130 struct IconEntry *entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
7131 BOOL update_entry = FALSE;
7133 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7135 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
7137 Remove(node);
7138 entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
7139 update_entry = TRUE;
7141 if (entry->ie_Flags & ICONENTRY_FLAG_FOCUS)
7143 entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
7144 update_entry = TRUE;
7148 if (update_entry)
7150 changed = TRUE;
7151 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
7152 data->update_entry = entry;
7153 MUI_Redraw(obj, MADF_DRAWUPDATE);
7157 if (changed)
7158 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
7160 return 1;
7164 ///MUIM_SelectAll()
7165 /**************************************************************************
7166 MUIM_SelectAll
7167 **************************************************************************/
7168 IPTR IconList__MUIM_IconList_SelectAll(struct IClass *CLASS, Object *obj, Msg message)
7170 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7171 struct IconEntry *node = NULL;
7172 BOOL changed = FALSE;
7174 #if defined(DEBUG_ILC_FUNCS)
7175 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7176 #endif
7178 node = (struct IconEntry *)GetHead(&data->icld_IconList);
7180 while (node != NULL)
7182 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7184 BOOL update_entry = FALSE;
7186 if (!(node->ie_Flags & ICONENTRY_FLAG_SELECTED))
7188 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
7189 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
7190 update_entry = TRUE;
7192 data->icld_SelectionLastClicked = node;
7194 else if (node->ie_Flags & ICONENTRY_FLAG_FOCUS)
7196 node->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
7197 update_entry = TRUE;
7200 if (update_entry)
7202 changed = TRUE;
7203 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
7204 data->update_entry = node;
7205 MUI_Redraw(obj, MADF_DRAWUPDATE);
7208 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
7211 if ((data->icld_SelectionLastClicked) && (data->icld_SelectionLastClicked != data->icld_FocusIcon))
7213 data->icld_FocusIcon = data->icld_SelectionLastClicked;
7214 if (!(data->icld_FocusIcon->ie_Flags & ICONENTRY_FLAG_FOCUS))
7216 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
7217 data->icld_FocusIcon->ie_Flags |= ICONENTRY_FLAG_FOCUS;
7218 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
7219 data->update_entry = data->icld_FocusIcon;
7220 MUI_Redraw(obj, MADF_DRAWUPDATE);
7224 if (changed)
7225 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
7227 return 1;
7231 ///IconList__MUIM_IconList_CoordsSort()
7232 IPTR IconList__MUIM_IconList_CoordsSort(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Sort *message)
7234 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7236 struct IconEntry *entry = NULL,
7237 *test_icon = NULL;
7239 struct List list_VisibleIcons;
7240 struct List list_HiddenIcons;
7241 // struct List list_UnplacedIcons;
7244 perform a quick sort of the iconlist based on entry coords
7245 this method DOESNT cause any visual output.
7247 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONSORTING)
7248 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7249 #endif
7251 NewList((struct List*)&list_VisibleIcons);
7252 NewList((struct List*)&list_HiddenIcons);
7254 /*move list into our local list struct(s)*/
7255 while ((entry = (struct IconEntry *)RemTail((struct List*)&data->icld_IconList)))
7257 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7259 AddHead((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
7261 else
7262 AddHead((struct List*)&list_HiddenIcons, (struct Node *)&entry->ie_IconNode);
7265 while ((entry = (struct IconEntry *)RemTail((struct List*)&list_VisibleIcons)))
7267 if ((test_icon = (struct IconEntry *)GetTail(&data->icld_IconList)) != NULL)
7269 while (test_icon != NULL)
7271 if (((data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconX > entry->ie_IconX)) ||
7272 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconY > entry->ie_IconY)))
7274 test_icon = (struct IconEntry *)GetPred(&test_icon->ie_IconNode);
7275 continue;
7277 else break;
7280 while (test_icon != NULL)
7282 if (((data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconY > entry->ie_IconY)) ||
7283 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconX > entry->ie_IconX)))
7285 test_icon = (struct IconEntry *)GetPred(&test_icon->ie_IconNode);
7286 continue;
7288 else break;
7290 Insert((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode, (struct Node *)&test_icon->ie_IconNode);
7292 else
7293 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7295 #if defined(DEBUG_ILC_ICONSORTING)
7296 D(bug("[IconList] %s: Done\n", __PRETTY_FUNCTION__));
7297 #endif
7299 while ((entry = (struct IconEntry *)RemTail((struct List*)&list_HiddenIcons)))
7301 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7304 #if defined(DEBUG_ILC_ICONSORTING_DUMP)
7305 #if defined(__AROS__)
7306 ForeachNode(&data->icld_IconList, entry)
7307 #else
7308 Foreach_Node(&data->icld_IconList, entry);
7309 #endif
7311 D(bug("[IconList] %s: %d %d '%s'\n", __PRETTY_FUNCTION__, entry->ie_IconX, entry->ie_IconY, entry->ie_IconListEntry.label));
7313 #endif
7315 return TRUE;
7319 ///MUIM_Sort()
7320 /**************************************************************************
7321 MUIM_Sort - sortsort
7322 **************************************************************************/
7323 IPTR IconList__MUIM_IconList_Sort(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Sort *message)
7325 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7326 struct IconEntry *entry = NULL,
7327 *icon1 = NULL,
7328 *icon2 = NULL;
7330 struct List list_VisibleIcons,
7331 list_SortedIcons,
7332 list_HiddenIcons;
7334 BOOL sortme, reversable = TRUE, enqueue = FALSE;
7335 int i, visible_count = 0;
7337 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONSORTING)
7338 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7339 #endif
7341 /* Reset incase view options have changed .. */
7342 data->icld_IconAreaLargestWidth = 0;
7343 data->icld_IconAreaLargestHeight = 0;
7344 data->icld_IconLargestHeight = 0;
7345 data->icld_LabelLargestHeight = 0;
7347 #if defined(DEBUG_ILC_ICONSORTING)
7348 D(bug("[IconList] %s: Sort-Flags : %x\n", __PRETTY_FUNCTION__, (data->icld_SortFlags & MUIV_IconList_Sort_MASK)));
7349 #endif
7350 NewList((struct List*)&list_VisibleIcons);
7351 NewList((struct List*)&list_SortedIcons);
7352 NewList((struct List*)&list_HiddenIcons);
7354 /*move list into our local list struct(s)*/
7355 while ((entry = (struct IconEntry *)RemTail((struct List*)&data->icld_IconList)))
7357 if (!(entry->ie_Flags & ICONENTRY_FLAG_HASICON))
7359 if (data->icld_DisplayFlags & ICONLIST_DISP_SHOWINFO)
7361 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7363 entry->ie_Flags &= ~(ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
7366 else if (!(entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
7368 entry->ie_Flags |= (ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
7371 else
7373 if (!(entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
7375 entry->ie_Flags |= (ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
7379 /* Now we have fixed visibility lets dump them into the correct list for sorting */
7380 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7382 if(entry->ie_AreaWidth > data->icld_IconAreaLargestWidth) data->icld_IconAreaLargestWidth = entry->ie_AreaWidth;
7383 if(entry->ie_AreaHeight > data->icld_IconAreaLargestHeight) data->icld_IconAreaLargestHeight = entry->ie_AreaHeight;
7384 if(entry->ie_IconHeight > data->icld_IconLargestHeight) data->icld_IconLargestHeight = entry->ie_IconHeight;
7385 if((entry->ie_AreaHeight - entry->ie_IconHeight) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = entry->ie_AreaHeight - entry->ie_IconHeight;
7387 if (((data->icld_SortFlags & MUIV_IconList_Sort_AutoSort) == 0) && (entry->ie_ProvidedIconX == NO_ICON_POSITION))
7388 AddTail((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
7389 else
7390 AddHead((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
7391 visible_count++;
7393 else
7395 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
7397 Remove(&entry->ie_SelectionNode);
7399 entry->ie_Flags &= ~(ICONENTRY_FLAG_SELECTED|ICONENTRY_FLAG_FOCUS);
7400 if (data->icld_SelectionLastClicked == entry) data->icld_SelectionLastClicked = NULL;
7401 if (data->icld_FocusIcon == entry) data->icld_FocusIcon = data->icld_SelectionLastClicked;
7402 AddHead((struct List*)&list_HiddenIcons, (struct Node *)&entry->ie_IconNode);
7406 /* Copy each visible entry back to the main list, sorting as we go*/
7407 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_VisibleIcons)))
7409 icon1 = (struct IconEntry *)GetHead(&list_SortedIcons);
7410 icon2 = NULL;
7412 sortme = FALSE;
7414 if (visible_count > 1)
7416 #if defined(DEBUG_ILC_ICONSORTING)
7417 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));
7418 #endif
7419 while (icon1)
7421 if(((icon1->ie_IconListEntry.type == ST_ROOT) || (icon1->ie_IconListEntry.type == ST_LINKDIR) || (icon1->ie_IconListEntry.type == ST_LINKFILE))
7422 || (data->icld_SortFlags & MUIV_IconList_Sort_DrawersMixed))
7424 /*volume list or drawers mixed*/
7425 sortme = TRUE;
7427 else
7429 /*drawers first*/
7430 if ((icon1->ie_IconListEntry.type == ST_USERDIR) && (entry->ie_IconListEntry.type == ST_USERDIR))
7432 sortme = TRUE;
7434 else
7436 if ((icon1->ie_IconListEntry.type != ST_USERDIR) && (entry->ie_IconListEntry.type != ST_USERDIR))
7437 sortme = TRUE;
7438 else
7440 /* we are the first drawer to arrive or we need to insert ourselves
7441 due to being sorted to the end of the drawers*/
7443 if ((!icon2 || icon2->ie_IconListEntry.type == ST_USERDIR) &&
7444 (entry->ie_IconListEntry.type == ST_USERDIR) &&
7445 (icon1->ie_IconListEntry.type != ST_USERDIR))
7447 #if defined(DEBUG_ILC_ICONSORTING)
7448 D(bug("[IconList] %s: force %s\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label));
7449 #endif
7450 break;
7456 if (sortme)
7458 i = 0;
7460 if ((data->icld_SortFlags & MUIV_IconList_Sort_AutoSort) == 0)
7462 if ((entry->ie_ProvidedIconX != NO_ICON_POSITION) && (entry->ie_ProvidedIconY != NO_ICON_POSITION))
7464 i = 1;
7468 if (i == 0)
7470 if (data->icld_SortFlags & MUIV_IconList_Sort_ByDate)
7472 /* Sort by Date */
7473 i = CompareDates((const struct DateStamp *)&entry->ie_FileInfoBlock->fib_Date,(const struct DateStamp *)&icon1->ie_FileInfoBlock->fib_Date);
7475 else if (data->icld_SortFlags & MUIV_IconList_Sort_BySize)
7477 /* Sort by Size .. */
7478 i = entry->ie_FileInfoBlock->fib_Size - icon1->ie_FileInfoBlock->fib_Size;
7480 else if ((data->icld_SortFlags & MUIV_IconList_Sort_ByType) && ((entry->ie_IconListEntry.type == ST_FILE) || (entry->ie_IconListEntry.type == ST_USERDIR)))
7482 /* Sort by Type .. */
7483 /* TODO: Sort icons based on type using datatypes */
7485 else
7487 /* Sort by Name .. */
7488 i = Stricmp(entry->ie_IconListEntry.label, icon1->ie_IconListEntry.label);
7489 if ((data->icld_SortFlags & MUIV_IconList_Sort_DrawersMixed) == 0) enqueue = TRUE;
7493 if ((reversable) && data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
7495 if (i > 0)
7496 break;
7498 else if (i < 0)
7499 break;
7501 icon2 = icon1;
7502 icon1 = (struct IconEntry *)GetSucc(&icon1->ie_IconNode);
7505 Insert((struct List*)&list_SortedIcons, (struct Node *)&entry->ie_IconNode, (struct Node *)&icon2->ie_IconNode);
7507 if (enqueue)
7509 /* Quickly resort based on node priorities .. */
7510 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_SortedIcons)))
7512 Enqueue((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7515 else
7517 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_SortedIcons)))
7519 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7523 DoMethod(obj, MUIM_IconList_PositionIcons);
7524 MUI_Redraw(obj, MADF_DRAWOBJECT);
7526 if ((data->icld_SortFlags & MUIV_IconList_Sort_Orders) != 0)
7528 DoMethod(obj, MUIM_IconList_CoordsSort);
7530 /* leave hidden icons on a seperate list to speed up normal list parsing ? */
7531 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_HiddenIcons)))
7533 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7536 SET(obj, MUIA_IconList_Changed, TRUE);
7538 return 1;
7542 ///MUIM_DragReport()
7543 /**************************************************************************
7544 MUIM_DragReport. Since MUI doesn't change the drop object if the dragged
7545 object is moved above another window (while still in the bounds of the
7546 orginal drop object) we must do it here manually to be compatible with
7547 MUI. Maybe Zune should fix this bug somewhen.
7548 **************************************************************************/
7549 IPTR IconList__MUIM_DragReport(struct IClass *CLASS, Object *obj, struct MUIP_DragReport *message)
7551 struct Window *wnd = _window(obj);
7552 struct Layer *l = NULL;
7554 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
7555 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7556 #endif
7558 LockLayerInfo(&wnd->WScreen->LayerInfo);
7559 l = WhichLayer(&wnd->WScreen->LayerInfo, wnd->LeftEdge + message->x, wnd->TopEdge + message->y);
7560 UnlockLayerInfo(&wnd->WScreen->LayerInfo);
7562 if (l != wnd->WLayer) return MUIV_DragReport_Abort;
7564 return MUIV_DragReport_Continue;
7568 ///MUIM_IconList_UnknownDropDestination()
7569 /**************************************************************************
7570 MUIM_IconList_UnknownDropDestination
7571 **************************************************************************/
7572 IPTR IconList__MUIM_UnknownDropDestination(struct IClass *CLASS, Object *obj, struct MUIP_UnknownDropDestination *message)
7574 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
7575 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7576 #endif
7577 #if defined(DEBUG_ILC_ICONDRAGDROP)
7578 D(bug("[IconList] %s: icons dropped on custom window \n", __PRETTY_FUNCTION__));
7579 #endif
7581 SET(obj, MUIA_IconList_AppWindowDrop, (IPTR)message); /* Now notify */
7583 return (IPTR)NULL;
7587 ///MUIM_IconList_MakeEntryVisible()
7588 /**************************************************************************
7589 Move the visible area so that the selected entry becomes visible ..
7590 **************************************************************************/
7591 IPTR IconList__MUIM_IconList_MakeEntryVisible(struct IClass *CLASS, Object *obj, struct MUIP_IconList_MakeEntryVisible *message)
7593 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7594 BOOL viewmoved = FALSE;
7595 struct Rectangle iconrect, viewrect;
7597 #if defined(DEBUG_ILC_FUNCS)
7598 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7599 #endif
7601 viewrect.MinX = data->icld_ViewX;
7602 viewrect.MaxX = data->icld_ViewX + data->icld_AreaWidth;
7603 viewrect.MinY = data->icld_ViewY;
7604 viewrect.MaxY = data->icld_ViewY + data->icld_AreaHeight;
7606 IconList_GetIconAreaRectangle(obj, data, message->entry, &iconrect);
7608 if (!(RectAndRect(&viewrect, &iconrect)))
7610 viewmoved = TRUE;
7611 if (message->entry->ie_IconX < data->icld_ViewX)
7612 data->icld_ViewX = message->entry->ie_IconX;
7613 else if (message->entry->ie_IconX > (data->icld_ViewX + data->icld_AreaWidth))
7614 data->icld_ViewX = (message->entry->ie_IconX + message->entry->ie_AreaWidth) - data->icld_AreaWidth;
7616 if (message->entry->ie_IconY < data->icld_ViewY)
7617 data->icld_ViewY = message->entry->ie_IconX;
7618 else if (message->entry->ie_IconY > (data->icld_ViewY + data->icld_AreaHeight))
7619 data->icld_ViewY = (message->entry->ie_IconY + message->entry->ie_AreaHeight) - data->icld_AreaHeight;
7622 if (viewmoved)
7624 #if defined(DEBUG_ILC_ICONRENDERING)
7625 D(bug("[IconList]: %s: call SetSuperAttrs()\n", __PRETTY_FUNCTION__));
7626 #endif
7627 SetSuperAttrs(CLASS, obj, MUIA_Virtgroup_Left, data->icld_ViewX,
7628 MUIA_Virtgroup_Top, data->icld_ViewY,
7629 TAG_DONE);
7631 #if defined(DEBUG_ILC_ICONRENDERING)
7632 D(bug("[IconList]: %s: call SetAttrs()\n", __PRETTY_FUNCTION__));
7633 #endif
7634 SetAttrs(obj, MUIA_Virtgroup_Left, data->icld_ViewX,
7635 MUIA_Virtgroup_Top, data->icld_ViewY,
7636 TAG_DONE);
7638 #if defined(DEBUG_ILC_ICONRENDERING)
7639 D(bug("[IconList]: %s: call MUI_Redraw()\n", __PRETTY_FUNCTION__));
7640 #endif
7641 MUI_Redraw(obj,MADF_DRAWOBJECT);
7643 return 1;
7646 #if defined(WANDERER_BUILTIN_ICONLIST)
7647 BOOPSI_DISPATCHER(IPTR,IconList_Dispatcher, CLASS, obj, message)
7649 #if defined(__AROS__)
7650 switch (message->MethodID)
7651 #else
7652 struct IClass *CLASS = cl;
7653 Msg message = msg;
7655 switch (msg->MethodID)
7656 #endif
7658 case OM_NEW: return IconList__OM_NEW(CLASS, obj, (struct opSet *)message);
7659 case OM_DISPOSE: return IconList__OM_DISPOSE(CLASS, obj, message);
7660 case OM_SET: return IconList__OM_SET(CLASS, obj, (struct opSet *)message);
7661 case OM_GET: return IconList__OM_GET(CLASS, obj, (struct opGet *)message);
7662 case OM_ADDMEMBER:
7663 case MUIM_Family_AddTail: return IconList__MUIM_Family_AddTail(CLASS, obj, (APTR)message);
7664 case MUIM_Family_AddHead: return IconList__MUIM_Family_AddHead(CLASS, obj, (APTR)message);
7665 case OM_REMMEMBER:
7666 case MUIM_Family_Remove: return IconList__MUIM_Family_Remove(CLASS, obj, (APTR)message);
7668 case MUIM_Setup: return IconList__MUIM_Setup(CLASS, obj, (struct MUIP_Setup *)message);
7670 case MUIM_Show: return IconList__MUIM_Show(CLASS,obj, (struct MUIP_Show *)message);
7671 case MUIM_Hide: return IconList__MUIM_Hide(CLASS,obj, (struct MUIP_Hide *)message);
7672 case MUIM_Cleanup: return IconList__MUIM_Cleanup(CLASS, obj, (struct MUIP_Cleanup *)message);
7673 case MUIM_AskMinMax: return IconList__MUIM_AskMinMax(CLASS, obj, (struct MUIP_AskMinMax *)message);
7674 case MUIM_Draw: return IconList__MUIM_Draw(CLASS, obj, (struct MUIP_Draw *)message);
7675 #if defined(__AROS__)
7676 case MUIM_Layout: return IconList__MUIM_Layout(CLASS, obj, (struct MUIP_Layout *)message);
7677 #endif
7678 case MUIM_HandleEvent: return IconList__MUIM_HandleEvent(CLASS, obj, (struct MUIP_HandleEvent *)message);
7679 case MUIM_CreateDragImage: return IconList__MUIM_CreateDragImage(CLASS, obj, (APTR)message);
7680 case MUIM_DeleteDragImage: return IconList__MUIM_DeleteDragImage(CLASS, obj, (APTR)message);
7681 case MUIM_DragQuery: return IconList__MUIM_DragQuery(CLASS, obj, (APTR)message);
7682 case MUIM_DragReport: return IconList__MUIM_DragReport(CLASS, obj, (APTR)message);
7683 case MUIM_DragDrop: return IconList__MUIM_DragDrop(CLASS, obj, (APTR)message);
7684 #if defined(__AROS__)
7685 case MUIM_UnknownDropDestination: return IconList__MUIM_UnknownDropDestination(CLASS, obj, (APTR)message);
7686 #endif
7687 case MUIM_IconList_Update: return IconList__MUIM_IconList_Update(CLASS, obj, (APTR)message);
7688 case MUIM_IconList_Clear: return IconList__MUIM_IconList_Clear(CLASS, obj, (APTR)message);
7689 case MUIM_IconList_RethinkDimensions: return IconList__MUIM_IconList_RethinkDimensions(CLASS, obj, (APTR)message);
7690 case MUIM_IconList_CreateEntry: return IconList__MUIM_IconList_CreateEntry(CLASS, obj, (APTR)message);
7691 case MUIM_IconList_UpdateEntry: return IconList__MUIM_IconList_UpdateEntry(CLASS, obj, (APTR)message);
7692 case MUIM_IconList_DestroyEntry: return IconList__MUIM_IconList_DestroyEntry(CLASS, obj, (APTR)message);
7693 case MUIM_IconList_DrawEntry: return IconList__MUIM_IconList_DrawEntry(CLASS, obj, (APTR)message);
7694 case MUIM_IconList_DrawEntryLabel: return IconList__MUIM_IconList_DrawEntryLabel(CLASS, obj, (APTR)message);
7695 case MUIM_IconList_NextIcon: return IconList__MUIM_IconList_NextIcon(CLASS, obj, (APTR)message);
7696 case MUIM_IconList_GetIconPrivate: return IconList__MUIM_IconList_GetIconPrivate(CLASS, obj, (APTR)message);
7697 case MUIM_IconList_UnselectAll: return IconList__MUIM_IconList_UnselectAll(CLASS, obj, (APTR)message);
7698 case MUIM_IconList_Sort: return IconList__MUIM_IconList_Sort(CLASS, obj, (APTR)message);
7699 case MUIM_IconList_CoordsSort: return IconList__MUIM_IconList_CoordsSort(CLASS, obj, (APTR)message);
7700 case MUIM_IconList_PositionIcons: return IconList__MUIM_IconList_PositionIcons(CLASS, obj, (APTR)message);
7701 case MUIM_IconList_SelectAll: return IconList__MUIM_IconList_SelectAll(CLASS, obj, (APTR)message);
7702 case MUIM_IconList_MakeEntryVisible: return IconList__MUIM_IconList_MakeEntryVisible(CLASS, obj, (APTR)message);
7705 return DoSuperMethodA(CLASS, obj, message);
7707 BOOPSI_DISPATCHER_END
7709 #if defined(__AROS__)
7710 /* Class descriptor. */
7711 const struct __MUIBuiltinClass _MUI_IconList_desc = {
7712 MUIC_IconList,
7713 MUIC_Area,
7714 sizeof(struct IconList_DATA),
7715 (void*)IconList_Dispatcher
7717 #endif
7718 #endif /* WANDERER_BUILTIN_ICONLIST */
7720 #if !defined(__AROS__)
7721 struct MUI_CustomClass *initIconListClass(void)
7723 return (struct MUI_CustomClass *) MUI_CreateCustomClass(NULL, MUIC_Area, NULL, sizeof(struct IconList_DATA), ENTRY(IconList_Dispatcher));
7725 #endif