Fixes to comments.
[AROS.git] / workbench / system / Wanderer / Classes / iconlist.c
blob5d080c9e8933b1bb081c3011159e74249e497856
1 /*
2 Copyright © 2001-2012, 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 <graphics/gfx.h>
40 #include <graphics/view.h>
41 #include <graphics/rpattr.h>
42 #include <workbench/icon.h>
43 #include <workbench/workbench.h>
45 #if defined(__AROS__)
46 #include <devices/rawkeycodes.h>
47 #include <clib/alib_protos.h>
48 #else
49 #include <devices_AROS/rawkeycodes.h>
50 #endif
53 #include <proto/exec.h>
54 #include <proto/graphics.h>
55 #include <proto/utility.h>
56 #include <proto/dos.h>
57 #include <proto/icon.h>
58 #include <proto/layers.h>
59 #include <proto/dos.h>
60 #include <proto/iffparse.h>
62 #if defined(__AROS__)
63 #include <prefs/prefhdr.h>
64 #include <prefs/wanderer.h>
65 #else
66 #include <prefs_AROS/prefhdr.h>
67 #include <prefs_AROS/wanderer.h>
68 #endif
70 #include <proto/cybergraphics.h>
72 #if defined(__AROS__)
73 #include <cybergraphx/cybergraphics.h>
74 #else
75 #include <cybergraphx_AROS/cybergraphics.h>
76 #endif
79 #if defined(__AMIGA__) && !defined(__PPC__)
80 #define NO_INLINE_STDARG
81 #endif
82 #include <proto/intuition.h>
83 #include <proto/muimaster.h>
84 #include <libraries/mui.h>
85 #include "iconlist_attributes.h"
86 #include "icon_attributes.h"
87 #include "iconlist.h"
88 #include "iconlist_private.h"
89 #include "iconlistview.h"
91 #if !defined(__AROS__)
92 #define DEBUG 1
94 #ifdef DEBUG
95 #define D(x) if (DEBUG) x
96 #ifdef __amigaos4__
97 #define bug DebugPrintF
98 #else
99 #define bug kprintf
100 #endif
101 #else
102 #define D(...)
103 #endif
104 #endif
106 #define _between(a,x,b) ((x)>=(a) && (x)<=(b))
107 #define _isinobject(x,y) (_between(_mleft(obj),(x),_mright (obj)) \
108 && _between(_mtop(obj) ,(y),_mbottom(obj)))
110 extern struct Library *MUIMasterBase;
112 static struct Hook __iconlist_UpdateLabels_hook;
114 // N.B: We Handle frame/background rendering so make sure icon.library doesnt do it ..
115 static struct TagItem __iconList_DrawIconStateTags[] = {
116 { ICONDRAWA_Frameless, TRUE },
117 { ICONDRAWA_Borderless, TRUE },
118 { ICONDRAWA_EraseBackground, FALSE },
119 { TAG_DONE, }
122 #if 0
123 static struct TagItem __iconList_BackBuffLayerTags[] =
125 { LA_Visible, FALSE },
126 { TAG_DONE, }
128 #endif
130 #ifndef NO_ICON_POSITION
131 #define NO_ICON_POSITION (0x8000000) /* belongs to workbench/workbench.h */
132 #endif
134 #define UPDATE_HEADERENTRY 1
135 #define UPDATE_SINGLEENTRY 2
136 #define UPDATE_SCROLL 3
137 #define UPDATE_RESIZE 4
139 #define LEFT_BUTTON 1
140 #define RIGHT_BUTTON 2
141 #define MIDDLE_BUTTON 4
143 #define ICONLIST_DRAWMODE_NORMAL 1
144 #define ICONLIST_DRAWMODE_FAST 2
146 /* Values used for List View-Mode */
147 #define COLOR_COLUMN_BACKGROUND 0
148 #define COLOR_COLUMN_BACKGROUND_SORTED 1
149 #define COLOR_COLUMN_BACKGROUND_LASSO 2
150 #define COLOR_COLUMN_BACKGROUND_LASSO_SORTED 3
152 #define COLOR_SELECTED_BACKGROUND 4
153 #define COLOR_SELECTED_BACKGROUND_SORTED 5
155 #define MIN_COLUMN_WIDTH 10
157 #define COLUMN_ALIGN_LEFT 0
158 #define COLUMN_ALIGN_CENTER 1
159 #define COLUMN_ALIGN_RIGHT 2
161 #define LINE_SPACING_TOP 2
162 #define LINE_SPACING_BOTTOM 2
163 #define LINE_EXTRAHEIGHT (LINE_SPACING_TOP + LINE_SPACING_BOTTOM)
165 #define LINE_SPACING_LEFT 1
166 #define LINE_SPACING_RIGHT 1
167 #define LINE_EXTRAWIDTH (LINE_SPACING_LEFT + LINE_SPACING_RIGHT)
169 #define ENTRY_SPACING_LEFT 1
170 #define ENTRY_SPACING_RIGHT 1
171 #define ENTRY_EXTRAWIDTH (ENTRY_SPACING_LEFT + ENTRY_SPACING_RIGHT)
173 #define HEADERLINE_SPACING_TOP 3
174 #define HEADERLINE_SPACING_BOTTOM 3
175 #define HEADERLINE_EXTRAHEIGHT (HEADERLINE_SPACING_TOP + HEADERLINE_SPACING_BOTTOM)
177 #define HEADERLINE_SPACING_LEFT 1
178 #define HEADERLINE_SPACING_RIGHT 1
179 #define HEADERLINE_EXTRAWIDTH (HEADERLINE_SPACING_LEFT + HEADERLINE_SPACING_RIGHT)
181 #define HEADERENTRY_SPACING_LEFT 4
182 #define HEADERENTRY_SPACING_RIGHT 4
183 #define HEADERENTRY_EXTRAWIDTH (HEADERENTRY_SPACING_LEFT + HEADERENTRY_SPACING_RIGHT)
185 enum
187 INDEX_TYPE,
188 INDEX_NAME,
189 INDEX_SIZE,
190 INDEX_PROTECTION,
191 INDEX_LASTACCESS,
192 INDEX_COMMENT
195 /**************************************************************************
196 Support Functions
197 **************************************************************************/
199 #define ForeachPrevNode(list, node) \
200 for \
202 node = (void *)(((struct List *)(list))->lh_TailPred); \
203 ((struct Node *)(node))->ln_Pred; \
204 node = (void *)(((struct Node *)(node))->ln_Pred) \
207 #define RPALPHAFLAT (1 << 0)
208 #define RPALPHARADIAL (1 << 1)
210 static void RastPortSetAlpha(struct RastPort *arport, ULONG ax, ULONG ay, ULONG width, ULONG height, UBYTE val, UBYTE alphamode)
212 ULONG x, y;
213 ULONG alphaval, pixelval;
214 APTR buffer, pixelptr;
216 if ((buffer = AllocVec(width * height * sizeof(ULONG), MEMF_ANY)) == NULL)
217 return;
219 ReadPixelArray(buffer, 0, 0, width * sizeof(ULONG), arport, 0, 0, width, height, RECTFMT_ARGB);
221 pixelptr = buffer;
223 for (y = 0; y < height; y++)
225 for (x = 0; x < width; x++)
227 if((pixelval = *((ULONG *)pixelptr)))
229 if (alphamode == RPALPHARADIAL){
230 //Set the alpha value based on distance from ax,ay
231 } else {
232 alphaval = val;
234 pixelval = (pixelval & 0xffffff00) | alphaval;
235 *((ULONG *)pixelptr) = pixelval;
237 pixelptr += sizeof(ULONG);
241 WritePixelArray(buffer, 0, 0, width * sizeof(ULONG), arport, 0, 0, width, height, RECTFMT_ARGB);
242 FreeVec(buffer);
245 ///RectAndRect()
246 // Entry/Label Area support functions
247 static int RectAndRect(struct Rectangle *a, struct Rectangle *b)
249 if ((a->MinX > b->MaxX) || (a->MinY > b->MaxY) || (a->MaxX < b->MinX) || (a->MaxY < b->MinY))
250 return 0;
251 return 1;
255 ///RegionAndRect()
256 static int RegionAndRect(struct Region * a, struct Rectangle *b)
258 D(bug("Region (%d, %d)(%d, %d), Rect (%d, %d)(%d, %d)\n",
259 (LONG)a->bounds.MinX, (LONG)a->bounds.MinY, (LONG)a->bounds.MaxX, (LONG)a->bounds.MaxY,
260 (LONG)b->MinX, (LONG)b->MinY, (LONG)b->MaxX, (LONG)b->MaxY));
262 /* First check with region bounds */
263 if (RectAndRect(&a->bounds, b) == 0)
264 return 0;
266 if (a->RegionRectangle)
268 struct RegionRectangle * c = a->RegionRectangle;
269 while(c)
271 struct Rectangle d = {
272 a->bounds.MinX + c->bounds.MinX,
273 a->bounds.MinY + c->bounds.MinY,
274 a->bounds.MinX + c->bounds.MaxX,
275 a->bounds.MinY + c->bounds.MaxY
276 }; /* We need absolute coordinates */
278 if (RectAndRect(&d, b))
279 return 1;
280 c = c->Next;
284 return 0;
287 ///Node_NextVisible()
288 // IconEntry List navigation functions ..
289 static struct IconEntry *Node_NextVisible(struct IconEntry *current_Node)
291 current_Node = (struct IconEntry *)GetSucc(&current_Node->ie_IconNode);
292 while ((current_Node != NULL) && (!(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
294 current_Node = (struct IconEntry *)GetSucc(&current_Node->ie_IconNode);
296 return current_Node;
300 ///Node_FirstVisible()
301 static struct IconEntry *Node_FirstVisible(struct List *icon_list)
303 struct IconEntry *current_Node = (struct IconEntry *)GetHead(icon_list);
305 if ((current_Node != NULL) && !(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE))
306 current_Node = Node_NextVisible(current_Node);
308 return current_Node;
312 ///Node_PreviousVisible()
313 static struct IconEntry *Node_PreviousVisible(struct IconEntry *current_Node)
315 current_Node = (struct IconEntry *)GetPred(&current_Node->ie_IconNode);
316 while ((current_Node != NULL) && (!(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
318 current_Node = (struct IconEntry *)GetPred(&current_Node->ie_IconNode);
320 return current_Node;
324 ///Node_LastVisible()
325 static struct IconEntry *Node_LastVisible(struct List *icon_list)
327 struct IconEntry *current_Node = (struct IconEntry *)GetTail(icon_list);
329 if ((current_Node != NULL) && !(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE))
330 current_Node = Node_PreviousVisible(current_Node);
332 return current_Node;
336 const UBYTE MSG_MEM_G[] = "GB";
337 const UBYTE MSG_MEM_M[] = "MB";
338 const UBYTE MSG_MEM_K[] = "KB";
339 const UBYTE MSG_MEM_B[] = "Bytes";
341 ///FmtSizeToString()
342 static void FmtSizeToString(UBYTE *buf, ULONG num)
344 UQUAD d;
345 const UBYTE *ch;
346 struct
348 IPTR val;
349 IPTR dec;
350 } array =
352 num,
356 if (num >= 1073741824)
358 //Gigabytes
359 array.val = num >> 30;
360 d = ((UQUAD)num * 10 + 536870912) / 1073741824;
361 array.dec = d % 10;
362 ch = MSG_MEM_G;
364 else if (num >= 1048576)
366 //Megabytes
367 array.val = num >> 20;
368 d = ((UQUAD)num * 10 + 524288) / 1048576;
369 array.dec = d % 10;
370 ch = MSG_MEM_M;
372 else if (num >= 1024)
374 //Kilobytes
375 array.val = num >> 10;
376 d = (num * 10 + 512) / 1024;
377 array.dec = d % 10;
378 ch = MSG_MEM_K;
380 else
382 //Bytes
383 array.val = num;
384 array.dec = 0;
385 d = 0;
386 ch = MSG_MEM_B;
389 if (!array.dec && (d > array.val * 10))
391 array.val++;
394 RawDoFmt(array.dec ? "%lu.%lu" : "%lu", &array, NULL, buf);
396 while (*buf)
398 buf++;
401 sprintf(buf, " %s", ch);
405 ///GetAbsoluteLassoRect()
406 // get positive lasso coords
407 static void GetAbsoluteLassoRect(struct IconList_DATA *data, struct Rectangle *LassoRectangle)
409 WORD minx = data->icld_LassoRectangle.MinX;
410 WORD miny = data->icld_LassoRectangle.MinY;
411 WORD maxx = data->icld_LassoRectangle.MaxX;
412 WORD maxy = data->icld_LassoRectangle.MaxY;
414 #if defined(DEBUG_ILC_LASSO) || defined(DEBUG_ILC_FUNCS)
415 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
416 #endif
418 if (minx > maxx)
420 /* Swap minx, maxx */
421 minx ^= maxx;
422 maxx ^= minx;
423 minx ^= maxx;
426 if (miny > maxy)
428 /* Swap miny, maxy */
429 miny ^= maxy;
430 maxy ^= miny;
431 miny ^= maxy;
434 LassoRectangle->MinX = data->view_rect.MinX - data->icld_ViewX + minx;
435 LassoRectangle->MinY = data->view_rect.MinY - data->icld_ViewY + miny;
436 LassoRectangle->MaxX = data->view_rect.MinX - data->icld_ViewX + maxx;
437 LassoRectangle->MaxY = data->view_rect.MinY - data->icld_ViewY + maxy;
441 ///IconList_InvertPixelRect()
442 static void IconList_InvertPixelRect(struct RastPort *rp, WORD minx, WORD miny, WORD maxx, WORD maxy, struct Rectangle *clip)
444 struct Rectangle r, clipped_r;
446 #if defined(DEBUG_ILC_RENDERING) || defined(DEBUG_ILC_FUNCS)
447 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
448 #endif
450 if (maxx < minx)
452 /* Swap minx, maxx */
453 minx ^= maxx;
454 maxx ^= minx;
455 minx ^= maxx;
458 if (maxy < miny)
460 /* Swap miny, maxy */
461 miny ^= maxy;
462 maxy ^= miny;
463 miny ^= maxy;
466 r.MinX = minx;
467 r.MinY = miny;
468 r.MaxX = maxx;
469 r.MaxY = maxy;
471 if (AndRectRect(&r, clip, &clipped_r))
473 InvertPixelArray(rp, clipped_r.MinX, clipped_r.MinY,
474 clipped_r.MaxX - clipped_r.MinX + 1, clipped_r.MaxY - clipped_r.MinY + 1);
479 ///IconList_InvertLassoOutlines()
480 // Simple lasso drawing by inverting area outlines
481 static void IconList_InvertLassoOutlines(Object *obj, struct IconList_DATA *data, struct Rectangle *rect)
483 struct Rectangle lasso;
484 struct Rectangle clip;
486 #if defined(DEBUG_ILC_LASSO) || defined(DEBUG_ILC_FUNCS)
487 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
488 #endif
490 /* get abolute iconlist coords */
491 lasso.MinX = rect->MinX + _mleft(obj);
492 lasso.MaxX = rect->MaxX + _mleft(obj);
493 lasso.MinY = rect->MinY + _mtop(obj);
494 lasso.MaxY = rect->MaxY + _mtop(obj);
496 clip.MinX = _mleft(obj);
497 clip.MinY = _mtop(obj);
498 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
500 clip.MinY += data->icld_LVMAttribs->lmva_HeaderHeight;
502 clip.MaxX = _mright(obj);
503 clip.MaxY = _mbottom(obj);
505 /* horizontal lasso lines */
506 IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MinY, lasso.MaxX-1, lasso.MinY + 1, &clip);
507 IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MaxY, lasso.MaxX-1, lasso.MaxY + 1, &clip);
509 /* vertical lasso lines */
510 IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MinY, lasso.MinX + 1, lasso.MaxY - 1, &clip);
511 IconList_InvertPixelRect(_rp(obj), lasso.MaxX, lasso.MinY, lasso.MaxX + 1, lasso.MaxY - 1, &clip);
515 ///IconList_GetIconImageRectangle()
516 //We don't use icon.library's label drawing so we do this by hand
517 static void IconList_GetIconImageRectangle(Object *obj, struct IconList_DATA *data, struct IconEntry *entry, struct Rectangle *rect)
519 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
520 D(bug("[IconList]: %s(entry @ %p)\n", __PRETTY_FUNCTION__, entry));
521 #endif
523 /* Get basic width/height */
524 GetIconRectangleA(NULL, entry->ie_DiskObj, NULL, rect, __iconList_DrawIconStateTags);
525 #if defined(DEBUG_ILC_ICONPOSITIONING)
526 D(bug("[IconList] %s: MinX %d, MinY %d MaxX %d, MaxY %d\n", __PRETTY_FUNCTION__, rect->MinX, rect->MinY, rect->MaxX, rect->MaxY));
527 #endif
528 entry->ie_IconWidth = (rect->MaxX - rect->MinX) + 1;
529 entry->ie_IconHeight = (rect->MaxY - rect->MinY) + 1;
531 if (entry->ie_IconHeight > data->icld_IconLargestHeight)
532 data->icld_IconLargestHeight = entry->ie_IconHeight;
536 ///IconList_GetIconImageOffsets()
537 static void IconList_GetIconImageOffsets(struct IconList_DATA *data, struct IconEntry *entry, LONG *offsetx, LONG *offsety)
539 *offsetx = *offsety = 0;
540 if (entry->ie_IconWidth < entry->ie_AreaWidth)
541 *offsetx += (entry->ie_AreaWidth - entry->ie_IconWidth)/2;
543 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
544 (entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
545 *offsetx += ((data->icld_IconAreaLargestWidth - entry->ie_AreaWidth)/2);
547 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
548 (entry->ie_AreaHeight < data->icld_IconAreaLargestHeight))
549 *offsety += ((data->icld_IconAreaLargestHeight - entry->ie_AreaHeight)/2);
552 ///IconList_GetIconLabelRectangle()
553 static void IconList_GetIconLabelRectangle(Object *obj, struct IconList_DATA *data, struct IconEntry *entry, struct Rectangle *rect)
555 ULONG outline_offset = 0;
556 ULONG textwidth = 0;
558 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
559 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
560 #endif
562 switch ( data->icld__Option_LabelTextMode )
564 case ICON_TEXTMODE_DROPSHADOW:
565 outline_offset = 1;
566 break;
568 case ICON_TEXTMODE_PLAIN:
569 break;
571 default:
572 outline_offset = 2;
573 break;
576 /* Get entry box width including text width */
577 if ((entry->ie_IconListEntry.label != NULL) && (entry->ie_TxtBuf_DisplayedLabel != NULL))
579 ULONG curlabel_TotalLines;
580 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
582 rect->MinX = 0;
583 rect->MaxX = (((data->icld__Option_LabelTextHorizontalPadding + data->icld__Option_LabelTextBorderWidth) * 2) + entry->ie_TxtBuf_DisplayedLabelWidth + outline_offset) - 1;
585 rect->MinY = 0;
587 curlabel_TotalLines = entry->ie_SplitParts;
588 if (curlabel_TotalLines == 0)
589 curlabel_TotalLines = 1;
590 if (curlabel_TotalLines > data->icld__Option_LabelTextMultiLine)
591 curlabel_TotalLines = data->icld__Option_LabelTextMultiLine;
593 rect->MaxY = (((data->icld__Option_LabelTextBorderHeight + data->icld__Option_LabelTextVerticalPadding) * 2) +
594 ((data->icld_IconLabelFont->tf_YSize + outline_offset) * curlabel_TotalLines)) - 1;
596 /* Date/size sorting has the date/size appended under the entry label
597 only list regular files like this (drawers have no size/date output) */
599 entry->ie_IconListEntry.type != ST_USERDIR &&
600 ((data->icld_SortFlags & MUIV_IconList_Sort_BySize) || (data->icld_SortFlags & MUIV_IconList_Sort_ByDate))
603 SetFont(data->icld_BufferRastPort, data->icld_IconInfoFont);
605 if( (data->icld_SortFlags & MUIV_IconList_Sort_BySize) && !(data->icld_SortFlags & MUIV_IconList_Sort_ByDate) )
607 entry->ie_TxtBuf_SIZEWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_SIZE, strlen(entry->ie_TxtBuf_SIZE));
608 textwidth = entry->ie_TxtBuf_SIZEWidth;
610 else
612 if( !(data->icld_SortFlags & MUIV_IconList_Sort_BySize) && (data->icld_SortFlags & MUIV_IconList_Sort_ByDate) )
614 if( entry->ie_Flags & ICONENTRY_FLAG_TODAY )
616 entry->ie_TxtBuf_TIMEWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_TIME, strlen(entry->ie_TxtBuf_TIME));
617 textwidth = entry->ie_TxtBuf_TIMEWidth;
619 else
621 entry->ie_TxtBuf_DATEWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_DATE, strlen(entry->ie_TxtBuf_DATE));
622 textwidth = entry->ie_TxtBuf_DATEWidth;
627 if (textwidth > 0)
629 rect->MaxY = rect->MaxY + data->icld_IconInfoFont->tf_YSize + outline_offset;
630 if ((textwidth + outline_offset + ((data->icld__Option_LabelTextHorizontalPadding + data->icld__Option_LabelTextBorderWidth) * 2)) > ((rect->MaxX - rect->MinX) + 1))
631 rect->MaxX = (textwidth + outline_offset + ((data->icld__Option_LabelTextVerticalPadding + data->icld__Option_LabelTextBorderWidth) * 2)) - 1;
635 if (((rect->MaxY - rect->MinY) + 1) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = ((rect->MaxY - rect->MinY) + 1);
639 ///IconList_GetIconAreaRectangle()
640 static void IconList_GetIconAreaRectangle(Object *obj, struct IconList_DATA *data, struct IconEntry *entry, struct Rectangle *rect)
642 struct Rectangle labelrect;
643 ULONG iconlabel_Width;
644 ULONG iconlabel_Height;
646 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
647 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
648 #endif
650 /* Get entry box width including text width */
651 memset(rect, 0, sizeof(struct Rectangle));
653 IconList_GetIconImageRectangle(obj, data, entry, rect);
655 entry->ie_AreaWidth = entry->ie_IconWidth;
656 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
658 entry->ie_AreaHeight = data->icld_IconLargestHeight;
660 else
662 entry->ie_AreaHeight = entry->ie_IconHeight;
665 IconList_GetIconLabelRectangle(obj, data, entry, &labelrect);
667 iconlabel_Width = ((labelrect.MaxX - labelrect.MinX) + 1);
668 iconlabel_Height = ((labelrect.MaxY - labelrect.MinY) + 1);
670 if (iconlabel_Width > entry->ie_AreaWidth)
671 entry->ie_AreaWidth = iconlabel_Width;
673 entry->ie_AreaHeight = entry->ie_AreaHeight + data->icld__Option_IconImageSpacing + iconlabel_Height;
675 /* Store */
676 rect->MaxX = (rect->MinX + entry->ie_AreaWidth) - 1;
677 rect->MaxY = (rect->MinY + entry->ie_AreaHeight) - 1;
679 if (entry->ie_AreaWidth > data->icld_IconAreaLargestWidth) data->icld_IconAreaLargestWidth = entry->ie_AreaWidth;
680 if (entry->ie_AreaHeight > data->icld_IconAreaLargestHeight) data->icld_IconAreaLargestHeight = entry->ie_AreaHeight;
684 static LONG FirstVisibleColumnNumber(struct IconList_DATA *data)
686 LONG i;
687 LONG retval = -1;
689 if (data->icld_LVMAttribs != NULL)
691 for(i = 0; i < NUM_COLUMNS; i++)
693 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
695 if (data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)
697 retval = i;
698 break;
703 return retval;
706 static LONG LastVisibleColumnNumber(struct IconList_DATA *data)
708 LONG i;
709 LONG retval = -1;
711 if (data->icld_LVMAttribs != NULL)
713 for(i = 0; i < NUM_COLUMNS; i++)
715 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
717 if (data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)
719 retval = i;
724 return retval;
728 static void RenderEntryField(Object *obj, struct IconList_DATA *data,
729 struct IconEntry *entry, struct Rectangle *rect, LONG index, BOOL firstvis,
730 BOOL lastvis, struct RastPort * rp)
732 STRPTR text = NULL, renderflag = "<UHOH>";
733 struct TextExtent te;
734 ULONG fit;
736 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
738 FillPixelArray(rp,
739 rect->MinX, rect->MinY,
740 rect->MaxX - rect->MinX + 1, rect->MaxY - rect->MinY,
741 0x0A246A);
744 rect->MinX += ENTRY_SPACING_LEFT;
745 rect->MaxX -= ENTRY_SPACING_RIGHT;
746 rect->MinY += LINE_SPACING_TOP;
747 rect->MaxY -= LINE_SPACING_BOTTOM;
749 if (firstvis) rect->MinX += LINE_SPACING_LEFT;
750 if (lastvis) rect->MaxX -= LINE_SPACING_RIGHT;
752 if (!entry) return;
754 switch(index)
756 case INDEX_TYPE:
757 /* Special case !! we draw an image instead .. */
758 text = renderflag;
759 break;
761 case INDEX_NAME:
762 text = entry->ie_IconListEntry.label;
763 break;
765 case INDEX_SIZE:
766 text = entry->ie_TxtBuf_SIZE;
767 break;
769 case INDEX_LASTACCESS:
770 text = AllocVec(strlen(entry->ie_TxtBuf_DATE) + strlen(entry->ie_TxtBuf_TIME) + 5, MEMF_CLEAR);
771 sprintf(text, "%s at %s", entry->ie_TxtBuf_DATE, entry->ie_TxtBuf_TIME);
772 break;
774 case INDEX_COMMENT:
775 text = entry->ie_FileInfoBlock->fib_Comment;
776 break;
778 case INDEX_PROTECTION:
779 text = entry->ie_TxtBuf_PROT;
780 break;
783 if (!text) return;
784 if (!text[0]) return;
786 if (text == renderflag)
788 if (entry->ie_IconListEntry.type == ST_USERDIR)
790 if (data->icld_LVMAttribs->lvma_IconDrawer)
792 DrawIconStateA
794 rp, data->icld_LVMAttribs->lvma_IconDrawer, NULL,
795 rect->MinX + 1, rect->MinY + 1,
796 (entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
797 __iconList_DrawIconStateTags
800 else
802 FillPixelArray(rp,
803 rect->MinX + 1, rect->MinY + 1,
804 rect->MaxX - rect->MinX - 1, rect->MaxY - rect->MinY - 1,
805 0xc0f0f0);
808 else
810 if (data->icld_LVMAttribs->lvma_IconFile)
812 DrawIconStateA
814 rp, data->icld_LVMAttribs->lvma_IconFile, NULL,
815 rect->MinX + 1, rect->MinY + 1,
816 (entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
817 __iconList_DrawIconStateTags
820 else
822 FillPixelArray(rp,
823 rect->MinX + 1, rect->MinY + 1,
824 rect->MaxX - rect->MinX - 1, rect->MaxY - rect->MinY - 1,
825 0xe0e0e0);
829 else
831 fit = TextFit(rp, text, strlen(text), &te, NULL, 1,
832 rect->MaxX - rect->MinX + 1,
833 rect->MaxY - rect->MinY + 1);
835 if (!fit) return;
837 SetABPenDrMd(rp, _pens(obj)[(entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? MPEN_SHINE : MPEN_TEXT], 0, JAM1);
839 if (((rect->MaxY - rect->MinY + 1) - data->icld_IconLabelFont->tf_YSize) > 0)
841 rect->MinY += ((rect->MaxY - rect->MinY + 1) - data->icld_IconLabelFont->tf_YSize)/2;
844 switch(data->icld_LVMAttribs->lmva_ColumnHAlign[index])
846 case COLUMN_ALIGN_LEFT:
847 Move(rp, rect->MinX, rect->MinY + rp->TxBaseline);
848 break;
850 case COLUMN_ALIGN_RIGHT:
851 Move(rp, rect->MaxX - te.te_Width, rect->MinY + rp->TxBaseline);
852 break;
854 case COLUMN_ALIGN_CENTER:
855 Move(rp, rect->MinX + (rect->MaxX - rect->MinX + 1 + 1 - te.te_Width) / 2,
856 rect->MinY + rp->TxBaseline);
857 break;
860 Text(rp, text, fit);
862 if ((index == INDEX_LASTACCESS) && text)
863 FreeVec(text);
867 /**************************************************************************
868 Draw the entry at its position
869 **************************************************************************/
870 ///IconList__MUIM_IconList_DrawEntry()
871 IPTR IconList__MUIM_IconList_DrawEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DrawEntry *message)
873 struct IconList_DATA *data = INST_DATA(CLASS, obj);
875 BOOL outside = FALSE;
877 struct Rectangle iconrect;
878 struct Rectangle objrect;
880 ULONG objX, objY, objW, objH;
881 LONG iconX, iconY;
883 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
885 objX = _mleft(obj);
886 objY = _mtop(obj);
888 else
890 objX = objY = 0;
892 objW = _mright(obj) - _mleft(obj) + 1;
893 objH = _mbottom(obj) - _mtop(obj) + 1;
895 #if defined(DEBUG_ILC_ICONRENDERING)
896 D(bug("[IconList]: %s(message->entry = 0x%p)\n", __PRETTY_FUNCTION__, message->entry));
897 #endif
899 if ((!(message->entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)) ||
900 (data->icld_BufferRastPort == NULL) ||
901 (!(message->entry->ie_DiskObj)))
903 #if defined(DEBUG_ILC_ICONRENDERING)
904 D(bug("[IconList] %s: Not visible or missing DOB\n", __PRETTY_FUNCTION__));
905 #endif
906 return FALSE;
909 /* Set the dimensions of our "view" */
910 objrect.MinX = objX;
911 objrect.MinY = objY;
912 objrect.MaxX = objX + objW - 1;
913 objrect.MaxY = objY + objH - 1;
915 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
917 struct Rectangle linerect;
918 LONG x, i;
919 LONG firstvis, lastvis;
921 linerect.MinX = objX - data->icld_ViewX;
922 linerect.MaxX = objX + objW - 1; //linerect.MinX + data->width - 1;
923 linerect.MinY = (objY - data->icld_ViewY) + data->icld_LVMAttribs->lmva_HeaderHeight + (message->drawmode * data->icld_LVMAttribs->lmva_RowHeight);
924 linerect.MaxY = linerect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
926 if (!AndRectRect(&linerect, &objrect, NULL)) return FALSE;
927 // if (!MustRenderRect(data, &linerect)) return;
929 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
931 x = linerect.MinX + LINE_SPACING_LEFT;
933 firstvis = FirstVisibleColumnNumber(data);
934 lastvis = LastVisibleColumnNumber(data);
936 for(i = 0; i < NUM_COLUMNS; i++)
938 struct Rectangle field_rect;
939 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
941 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[i] & LVMCF_COLVISIBLE)) continue;
943 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
944 field_rect.MinY = linerect.MinY;
945 field_rect.MaxX = x + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1 + ((i == lastvis) ? LINE_SPACING_RIGHT : 0);
946 field_rect.MaxY = linerect.MaxY;
948 /* if (MustRenderRect(data, &field_rect))
950 if (AndRectRect(&field_rect, &objrect, NULL))
952 RenderEntryField(obj, data, message->entry, &field_rect, index,
953 (i == firstvis), (i == lastvis), data->icld_BufferRastPort);
955 /* }*/
956 x += data->icld_LVMAttribs->lmva_ColumnWidth[index];
959 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_ROWDRAWTOEND) == LVMAF_ROWDRAWTOEND)
961 x += LINE_SPACING_RIGHT;
963 if (x < linerect.MaxX)
965 linerect.MinX = x;
967 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_SHINE], 0, JAM1);
968 RectFill(data->icld_BufferRastPort, linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
972 else
974 LONG offsetx,offsety;
976 /* Get the dimensions and affected area of message->entry */
977 IconList_GetIconImageRectangle(obj, data, message->entry, &iconrect);
979 /* Get offset corrections */
980 IconList_GetIconImageOffsets(data, message->entry, &offsetx, &offsety);
982 /* Add the relative position offset of the message->entry */
983 iconrect.MinX += objX - data->icld_ViewX + message->entry->ie_IconX + offsetx;
984 iconrect.MaxX += objX - data->icld_ViewX + message->entry->ie_IconX + offsetx;
985 iconrect.MinY += objY - data->icld_ViewY + message->entry->ie_IconY + offsety;
986 iconrect.MaxY += objY - data->icld_ViewY + message->entry->ie_IconY + offsety;
988 if (!RectAndRect(&iconrect, &objrect))
990 #if defined(DEBUG_ILC_ICONRENDERING)
991 D(bug("[IconList] %s: Entry '%s' image outside of visible area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
992 #endif
993 return FALSE;
996 /* data->update_rect1 and data->update_rect2 may
997 point to rectangles to indicate that only icons
998 in any of this rectangles need to be drawn */
999 if (data->update_rect1)
1001 if (!RectAndRect(&iconrect, data->update_rect1)) outside = TRUE;
1004 if (data->update_rect2)
1006 if (data->update_rect1)
1008 if ((outside == TRUE) && RectAndRect(&iconrect, data->update_rect2))
1009 outside = FALSE;
1011 else
1013 if (!RectAndRect(&iconrect, data->update_rect2))
1014 outside = TRUE;
1018 if (outside == TRUE)
1020 #if defined(DEBUG_ILC_ICONRENDERING)
1021 D(bug("[IconList] %s: Entry '%s' image outside of update area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1022 #endif
1023 return FALSE;
1026 if (message->drawmode == ICONENTRY_DRAWMODE_NONE) return TRUE;
1028 // Center entry image
1029 iconX = iconrect.MinX - objX + data->icld_DrawOffsetX;
1030 iconY = iconrect.MinY - objY + data->icld_DrawOffsetY;
1032 #if defined(DEBUG_ILC_ICONRENDERING)
1033 D(bug("[IconList] %s: DrawIconState('%s') .. %d, %d\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label, iconX, iconY));
1034 #endif
1035 DrawIconStateA
1037 data->icld_BufferRastPort, message->entry->ie_DiskObj, NULL,
1038 iconX,
1039 iconY,
1040 (message->entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
1041 __iconList_DrawIconStateTags
1043 #if defined(DEBUG_ILC_ICONRENDERING)
1044 D(bug("[IconList] %s: DrawIconState Done\n", __PRETTY_FUNCTION__));
1045 #endif
1048 return TRUE;
1052 ///IconList__LabelFunc_SplitLabel()
1053 static void IconList__LabelFunc_SplitLabel(Object *obj, struct IconList_DATA *data, struct IconEntry *entry)
1055 ULONG labelSplit_MaxLabelLineLength = data->icld__Option_LabelTextMaxLen;
1056 ULONG labelSplit_LabelLength = strlen(entry->ie_IconListEntry.label);
1057 ULONG txwidth;
1058 // ULONG labelSplit_FontY = data->icld_IconLabelFont->tf_YSize;
1059 int labelSplit_CharsDone, labelSplit_CharsSplit;
1060 ULONG labelSplit_CurSplitWidth;
1062 if ((data->icld__Option_TrimVolumeNames) &&
1063 ((entry->ie_IconListEntry.type == ST_ROOT) && (entry->ie_IconListEntry.label[labelSplit_LabelLength - 1] == ':')))
1064 labelSplit_LabelLength--;
1066 if (labelSplit_MaxLabelLineLength >= labelSplit_LabelLength)
1068 #if defined(DEBUG_ILC_ICONRENDERING)
1069 D(bug("[IconList]: %s: Label'%s' doesnt need split (onyl %d chars)\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label, labelSplit_LabelLength));
1070 #endif
1071 return;
1074 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
1075 txwidth = TextLength(data->icld_BufferRastPort, entry->ie_IconListEntry.label, labelSplit_MaxLabelLineLength);
1076 #if defined(DEBUG_ILC_ICONRENDERING)
1077 D(bug("[IconList]: %s: txwidth = %d\n", __PRETTY_FUNCTION__, txwidth));
1078 #endif
1079 entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, 256);
1080 memset(entry->ie_TxtBuf_DisplayedLabel, 0, 256);
1081 entry->ie_SplitParts = 0;
1083 labelSplit_CharsDone = 0;
1084 labelSplit_CharsSplit = 0;
1086 while (labelSplit_CharsDone < labelSplit_LabelLength)
1088 ULONG labelSplit_CurSplitLength = labelSplit_LabelLength - labelSplit_CharsDone;
1089 IPTR labelSplit_SplitStart = (IPTR)(entry->ie_IconListEntry.label + labelSplit_CharsDone);
1090 int tmp_checkoffs = 0;
1091 IPTR labelSplit_RemainingCharsAfterSplit;
1092 IPTR labelSplit_CurSplitDest;
1094 while (*(char *)(labelSplit_SplitStart) == ' ')
1096 //Skip preceding spaces..
1097 labelSplit_SplitStart = labelSplit_SplitStart + 1;
1098 labelSplit_CurSplitLength = labelSplit_CurSplitLength - 1;
1099 labelSplit_CharsDone = labelSplit_CharsDone + 1;
1102 while(TextLength(data->icld_BufferRastPort, (char *)labelSplit_SplitStart, labelSplit_CurSplitLength) < txwidth) labelSplit_CurSplitLength++;
1103 while(TextLength(data->icld_BufferRastPort, (char *)labelSplit_SplitStart, labelSplit_CurSplitLength) > txwidth) labelSplit_CurSplitLength--;
1104 #if defined(DEBUG_ILC_ICONRENDERING)
1105 D(bug("[IconList]: %s: labelSplit_CurSplitLength = %d\n", __PRETTY_FUNCTION__, labelSplit_CurSplitLength));
1106 #endif
1108 #if defined(DEBUG_ILC_ICONRENDERING)
1109 D(bug("[IconList]: %s: Attempting to find neat split ", __PRETTY_FUNCTION__));
1110 #endif
1111 while(tmp_checkoffs < (labelSplit_CurSplitLength - ILC_ICONLABEL_SHORTEST))
1113 #if defined(DEBUG_ILC_ICONRENDERING)
1114 D(bug("%d", tmp_checkoffs));
1115 #endif
1116 labelSplit_RemainingCharsAfterSplit = labelSplit_LabelLength - (labelSplit_CharsDone + labelSplit_CurSplitLength);
1118 if ((labelSplit_CurSplitLength - tmp_checkoffs) > ILC_ICONLABEL_SHORTEST)
1120 #if defined(DEBUG_ILC_ICONRENDERING)
1121 D(bug("<"));
1122 #endif
1123 if ((*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == ' ') ||
1124 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == '.') ||
1125 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == '-'))
1127 #if defined(DEBUG_ILC_ICONRENDERING)
1128 D(bug("!"));
1129 #endif
1130 labelSplit_CurSplitLength = labelSplit_CurSplitLength - tmp_checkoffs;
1131 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit - tmp_checkoffs;
1132 tmp_checkoffs = 0;
1133 break;
1137 if ((labelSplit_RemainingCharsAfterSplit - tmp_checkoffs) < 0)
1139 #if defined(DEBUG_ILC_ICONRENDERING)
1140 D(bug("="));
1141 #endif
1142 labelSplit_CurSplitLength = labelSplit_CurSplitLength + tmp_checkoffs;
1143 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit + tmp_checkoffs;
1144 tmp_checkoffs = 0;
1145 break;
1148 if ((labelSplit_RemainingCharsAfterSplit - tmp_checkoffs) >= ILC_ICONLABEL_SHORTEST)
1150 #if defined(DEBUG_ILC_ICONRENDERING)
1151 D(bug(">"));
1152 #endif
1153 if ((*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == ' ') ||
1154 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == '.') ||
1155 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == '-'))
1157 #if defined(DEBUG_ILC_ICONRENDERING)
1158 D(bug("!"));
1159 #endif
1160 labelSplit_CurSplitLength = labelSplit_CurSplitLength + tmp_checkoffs;
1161 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit + tmp_checkoffs;
1162 tmp_checkoffs = 0;
1163 break;
1167 tmp_checkoffs = tmp_checkoffs + 1;
1169 #if defined(DEBUG_ILC_ICONRENDERING)
1170 D(bug("\n"));
1171 #endif
1172 if (tmp_checkoffs != 0)
1174 #if defined(DEBUG_ILC_ICONRENDERING)
1175 D(bug("[IconList]: %s: Couldnt find neat split : Still %d chars\n", __PRETTY_FUNCTION__, labelSplit_RemainingCharsAfterSplit));
1176 #endif
1177 if (labelSplit_RemainingCharsAfterSplit <= ILC_ICONLABEL_SHORTEST)
1179 labelSplit_CurSplitLength = labelSplit_CurSplitLength + (labelSplit_RemainingCharsAfterSplit - ILC_ICONLABEL_SHORTEST);
1182 if ((labelSplit_CharsDone + labelSplit_CurSplitLength) > labelSplit_LabelLength) labelSplit_CurSplitLength = labelSplit_LabelLength - labelSplit_CharsDone;
1184 labelSplit_CurSplitDest = (IPTR)(entry->ie_TxtBuf_DisplayedLabel + labelSplit_CharsSplit + entry->ie_SplitParts);
1186 strncpy((char *)labelSplit_CurSplitDest, (char *)labelSplit_SplitStart, labelSplit_CurSplitLength);
1188 labelSplit_CurSplitWidth = TextLength(data->icld_BufferRastPort, (char *)labelSplit_CurSplitDest, labelSplit_CurSplitLength);
1190 entry->ie_SplitParts = entry->ie_SplitParts + 1;
1192 labelSplit_CharsDone = labelSplit_CharsDone + labelSplit_CurSplitLength;
1193 labelSplit_CharsSplit = labelSplit_CharsSplit + labelSplit_CurSplitLength;
1195 if (labelSplit_CurSplitWidth > entry->ie_TxtBuf_DisplayedLabelWidth) entry->ie_TxtBuf_DisplayedLabelWidth = labelSplit_CurSplitWidth;
1197 if ((entry->ie_SplitParts <= 1) && entry->ie_TxtBuf_DisplayedLabel)
1199 FreeVecPooled(data->icld_Pool, entry->ie_TxtBuf_DisplayedLabel);
1200 entry->ie_TxtBuf_DisplayedLabel = NULL;
1201 entry->ie_SplitParts = 0;
1203 // if ((labelSplit_FontY * entry->ie_SplitParts) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = (labelSplit_FontY * entry->ie_SplitParts);
1207 ///IconList__LabelFunc_CreateLabel()
1208 static IPTR IconList__LabelFunc_CreateLabel(Object *obj, struct IconList_DATA *data, struct IconEntry *entry)
1210 #if defined(DEBUG_ILC_ICONRENDERING) || defined(DEBUG_ILC_FUNCS)
1211 D(bug("[IconList]: %s('%s')\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label));
1212 #endif
1213 if (entry->ie_TxtBuf_DisplayedLabel)
1215 FreeVecPooled(data->icld_Pool, entry->ie_TxtBuf_DisplayedLabel);
1216 entry->ie_TxtBuf_DisplayedLabel = NULL;
1217 entry->ie_SplitParts = 0;
1220 if (data->icld__Option_LabelTextMultiLine > 1)
1222 #if defined(DEBUG_ILC_ICONRENDERING)
1223 D(bug("[IconList]: %s: Attempting to split label ..\n", __PRETTY_FUNCTION__));
1224 #endif
1225 IconList__LabelFunc_SplitLabel(obj, data, entry);
1228 if (entry->ie_TxtBuf_DisplayedLabel == NULL)
1230 ULONG ie_LabelLength = strlen(entry->ie_IconListEntry.label);
1231 entry->ie_SplitParts = 1;
1233 #if defined(DEBUG_ILC_ICONRENDERING)
1234 D(bug("[IconList]: %s: Building unsplit label (len = %d) ..\n", __PRETTY_FUNCTION__, ie_LabelLength));
1235 #endif
1237 if ((data->icld__Option_TrimVolumeNames) &&
1238 ((entry->ie_IconListEntry.type == ST_ROOT) && (entry->ie_IconListEntry.label[ie_LabelLength - 1] == ':')))
1239 ie_LabelLength--;
1241 if(ie_LabelLength > data->icld__Option_LabelTextMaxLen)
1243 if (!(entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, data->icld__Option_LabelTextMaxLen + 1)))
1245 return (IPTR)NULL;
1247 memset(entry->ie_TxtBuf_DisplayedLabel, 0, data->icld__Option_LabelTextMaxLen + 1);
1248 strncpy(entry->ie_TxtBuf_DisplayedLabel, entry->ie_IconListEntry.label, data->icld__Option_LabelTextMaxLen - 3);
1249 strcat(entry->ie_TxtBuf_DisplayedLabel , " ..");
1251 else
1253 if (!(entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, ie_LabelLength + 1)))
1255 return (IPTR)NULL;
1257 memset(entry->ie_TxtBuf_DisplayedLabel, 0, ie_LabelLength + 1);
1258 strncpy(entry->ie_TxtBuf_DisplayedLabel, entry->ie_IconListEntry.label, ie_LabelLength );
1260 entry->ie_TxtBuf_DisplayedLabelWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_DisplayedLabel, strlen(entry->ie_TxtBuf_DisplayedLabel));
1261 // if ((data->icld_IconLabelFont->tf_YSize) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = data->icld_IconLabelFont->tf_YSize;
1264 // if (entry->ie_TxtBuf_DisplayedLabelWidth > data->icld_LabelLargestWidth) data->icld_LabelLargestWidth = entry->ie_TxtBuf_DisplayedLabelWidth;
1266 return (IPTR)entry->ie_TxtBuf_DisplayedLabel;
1270 ///IconList__HookFunc_UpdateLabelsFunc()
1271 AROS_UFH3(
1272 void, IconList__HookFunc_UpdateLabelsFunc,
1273 AROS_UFHA(struct Hook *, hook, A0),
1274 AROS_UFHA(APTR *, obj, A2),
1275 AROS_UFHA(APTR, param, A1)
1278 AROS_USERFUNC_INIT
1280 /* Get our private data */
1281 Class *CLASS = *( Class **)param;
1282 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1284 #if defined(DEBUG_ILC_LASSO) || defined(DEBUG_ILC_FUNCS)
1285 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1286 #endif
1288 if (((data->icld__Option_LabelTextMaxLen != data->icld__Option_LastLabelTextMaxLen) &&
1289 (data->icld__Option_LabelTextMultiLine > 1)) ||
1290 (data->icld__Option_LabelTextMultiLine != data->icld__Option_LastLabelTextMultiLine));
1292 struct IconEntry *iconentry_Current = NULL;
1293 #if defined(__AROS__)
1294 ForeachNode(&data->icld_IconList, iconentry_Current)
1295 #else
1296 Foreach_Node(&data->icld_IconList, iconentry_Current);
1297 #endif
1299 IconList__LabelFunc_CreateLabel((Object *)obj, data, iconentry_Current);
1303 data->icld__Option_LastLabelTextMaxLen = data->icld__Option_LabelTextMaxLen;
1304 data->icld__Option_LastLabelTextMultiLine = data->icld__Option_LabelTextMultiLine;
1306 AROS_USERFUNC_EXIT
1310 ///IconList__MUIM_IconList_DrawEntryLabel()
1311 IPTR IconList__MUIM_IconList_DrawEntryLabel(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DrawEntry *message)
1313 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1315 STRPTR buf = NULL;
1316 BOOL outside = FALSE;
1318 struct Rectangle iconlabelrect;
1319 struct Rectangle objrect;
1321 ULONG txtbox_width = 0;
1322 LONG tx,ty,offsetx,offsety;
1323 LONG txwidth; // txheight;
1325 ULONG objX, objY, objW, objH;
1326 LONG labelX, labelY;
1328 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1329 return FALSE;
1331 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
1333 objX = _mleft(obj);
1334 objY = _mtop(obj);
1336 else
1338 objX = objY = 0;
1340 objW = _mright(obj) - _mleft(obj) + 1;
1341 objH = _mbottom(obj) - _mtop(obj) + 1;
1343 ULONG txtarea_width;
1344 ULONG curlabel_TotalLines, curlabel_CurrentLine, offset_y;
1346 #if defined(DEBUG_ILC_ICONRENDERING) || defined(DEBUG_ILC_FUNCS)
1347 D(bug("[IconList]: %s(message->entry = 0x%p), '%s'\n", __PRETTY_FUNCTION__, message->entry, message->entry->ie_IconListEntry.label));
1348 #endif
1350 if ((!(message->entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)) ||
1351 (data->icld_BufferRastPort == NULL) ||
1352 (!(message->entry->ie_DiskObj)))
1354 #if defined(DEBUG_ILC_ICONRENDERING)
1355 D(bug("[IconList] %s: Not visible or missing DOB\n", __PRETTY_FUNCTION__));
1356 #endif
1357 return FALSE;
1360 /* Get the dimensions and affected area of message->entry's label */
1361 IconList_GetIconLabelRectangle(obj, data, message->entry, &iconlabelrect);
1363 /* Add the relative position offset of the message->entry's label */
1364 offsetx = (objX - data->icld_ViewX) + message->entry->ie_IconX;
1365 txtbox_width = (iconlabelrect.MaxX - iconlabelrect.MinX) + 1;
1367 if (txtbox_width < message->entry->ie_AreaWidth)
1368 offsetx += ((message->entry->ie_AreaWidth - txtbox_width)/2);
1370 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1371 (message->entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
1372 offsetx += ((data->icld_IconAreaLargestWidth - message->entry->ie_AreaWidth)/2);
1374 iconlabelrect.MinX += offsetx;
1375 iconlabelrect.MaxX += offsetx;
1377 offsety = (objY - data->icld_ViewY) + message->entry->ie_IconY + data->icld__Option_IconImageSpacing;
1378 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1379 (message->entry->ie_AreaHeight < data->icld_IconAreaLargestHeight))
1380 offsety += ((data->icld_IconAreaLargestHeight - message->entry->ie_AreaHeight)/2);
1382 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1384 offsety = offsety + data->icld_IconLargestHeight;
1386 else
1388 offsety = offsety + message->entry->ie_IconHeight;
1390 iconlabelrect.MinY += offsety;
1391 iconlabelrect.MaxY += offsety;
1393 /* Add the relative position of the window */
1394 objrect.MinX = objX;
1395 objrect.MinY = objX;
1396 objrect.MaxX = objX + objW;
1397 objrect.MaxY = objY + objH;
1399 if (!RectAndRect(&iconlabelrect, &objrect))
1401 #if defined(DEBUG_ILC_ICONRENDERING)
1402 (bug("[IconList] %s: Entry '%s' label outside of visible area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1403 #endif
1404 return FALSE;
1407 /* data->update_rect1 and data->update_rect2 may
1408 point to rectangles to indicate that only icons
1409 in any of this rectangles need to be drawn */
1410 if (data->update_rect1)
1412 if (!RectAndRect(&iconlabelrect, data->update_rect1))
1413 outside = TRUE;
1416 if (data->update_rect2)
1418 if (data->update_rect1)
1420 if ((outside == TRUE) && RectAndRect(&iconlabelrect, data->update_rect2))
1421 outside = FALSE;
1423 else
1425 if (!RectAndRect(&iconlabelrect, data->update_rect2))
1426 outside = TRUE;
1430 if (outside == TRUE)
1432 #if defined(DEBUG_ILC_ICONRENDERING)
1433 D(bug("[IconList] %s: Entry '%s' label outside of update area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1434 #endif
1435 return FALSE;
1438 if (message->drawmode == ICONENTRY_DRAWMODE_NONE)
1439 return TRUE;
1441 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_TEXT], 0, JAM1);
1443 iconlabelrect.MinX = (iconlabelrect.MinX - objX) + data->icld_DrawOffsetX;
1444 iconlabelrect.MinY = (iconlabelrect.MinY - objY) + data->icld_DrawOffsetY;
1445 iconlabelrect.MaxX = (iconlabelrect.MaxX - objX) + data->icld_DrawOffsetX;
1446 iconlabelrect.MaxY = (iconlabelrect.MaxY - objY) + data->icld_DrawOffsetY;
1448 labelX = iconlabelrect.MinX + data->icld__Option_LabelTextBorderWidth + data->icld__Option_LabelTextHorizontalPadding;
1449 labelY = iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight + data->icld__Option_LabelTextVerticalPadding;
1451 txtarea_width = txtbox_width - ((data->icld__Option_LabelTextBorderWidth + data->icld__Option_LabelTextHorizontalPadding) * 2);
1453 #if defined(DEBUG_ILC_ICONRENDERING)
1454 D(bug("[IconList] %s: Drawing Label '%s' .. %d, %d\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label, labelX, labelY));
1455 #endif
1456 if (message->entry->ie_IconListEntry.label && message->entry->ie_TxtBuf_DisplayedLabel)
1458 char *curlabel_StrPtr;
1460 if ((message->entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
1462 //Draw the focus box around the selected label ..
1463 if (data->icld__Option_LabelTextBorderHeight > 0)
1465 InvertPixelArray(data->icld_BufferRastPort,
1466 iconlabelrect.MinX, iconlabelrect.MinY,
1467 (iconlabelrect.MaxX - iconlabelrect.MinX) + 1, data->icld__Option_LabelTextBorderHeight);
1469 InvertPixelArray(data->icld_BufferRastPort,
1470 iconlabelrect.MinX, iconlabelrect.MaxY - (data->icld__Option_LabelTextBorderHeight - 1),
1471 (iconlabelrect.MaxX - iconlabelrect.MinX) + 1, data->icld__Option_LabelTextBorderHeight);
1473 if (data->icld__Option_LabelTextBorderWidth > 0)
1475 InvertPixelArray(data->icld_BufferRastPort,
1476 iconlabelrect.MinX, iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight,
1477 data->icld__Option_LabelTextBorderWidth, (((iconlabelrect.MaxY - iconlabelrect.MinY) + 1) - (data->icld__Option_LabelTextBorderHeight * 2)));
1479 InvertPixelArray(data->icld_BufferRastPort,
1480 iconlabelrect.MaxX - (data->icld__Option_LabelTextBorderWidth - 1), iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight,
1481 data->icld__Option_LabelTextBorderWidth, (((iconlabelrect.MaxY - iconlabelrect.MinY) + 1) - (data->icld__Option_LabelTextBorderHeight * 2)));
1485 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
1487 curlabel_TotalLines = message->entry->ie_SplitParts;
1488 curlabel_CurrentLine = 0;
1490 if (curlabel_TotalLines == 0)
1491 curlabel_TotalLines = 1;
1493 if (!(data->icld__Option_LabelTextMultiLineOnFocus) || (data->icld__Option_LabelTextMultiLineOnFocus && (message->entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
1495 if (curlabel_TotalLines > data->icld__Option_LabelTextMultiLine)
1496 curlabel_TotalLines = data->icld__Option_LabelTextMultiLine;
1498 else
1499 curlabel_TotalLines = 1;
1501 curlabel_StrPtr = message->entry->ie_TxtBuf_DisplayedLabel;
1503 ty = labelY - 1;
1505 #if defined(DEBUG_ILC_ICONRENDERING)
1506 D(bug("[IconList] %s: Font YSize %d Baseline %d\n", __PRETTY_FUNCTION__,data->icld_IconLabelFont->tf_YSize, data->icld_IconLabelFont->tf_Baseline));
1507 #endif
1508 for (curlabel_CurrentLine = 0; curlabel_CurrentLine < curlabel_TotalLines; curlabel_CurrentLine++)
1510 ULONG ie_LabelLength;
1512 if (curlabel_CurrentLine > 0) curlabel_StrPtr = curlabel_StrPtr + strlen(curlabel_StrPtr) + 1;
1513 if ((curlabel_CurrentLine >= (curlabel_TotalLines -1)) && (curlabel_TotalLines < message->entry->ie_SplitParts))
1515 char *tmpLine = curlabel_StrPtr;
1516 ULONG tmpLen = strlen(tmpLine);
1518 if ((curlabel_StrPtr = AllocVecPooled(data->icld_Pool, tmpLen + 1)) != NULL)
1520 memset(curlabel_StrPtr, 0, tmpLen + 1);
1521 strncpy(curlabel_StrPtr, tmpLine, tmpLen - 3);
1522 strcat(curlabel_StrPtr , " ..");
1524 else
1525 return FALSE;
1529 ie_LabelLength = strlen(curlabel_StrPtr);
1530 offset_y = 0;
1532 // Center message->entry's label
1533 tx = (labelX + (message->entry->ie_TxtBuf_DisplayedLabelWidth / 2) - (TextLength(data->icld_BufferRastPort, curlabel_StrPtr, strlen(curlabel_StrPtr)) / 2));
1535 if (message->entry->ie_TxtBuf_DisplayedLabelWidth < txtarea_width)
1536 tx += ((txtarea_width - message->entry->ie_TxtBuf_DisplayedLabelWidth)/2);
1538 ty = ty + data->icld_IconLabelFont->tf_YSize;
1540 switch ( data->icld__Option_LabelTextMode )
1542 case ICON_TEXTMODE_DROPSHADOW:
1543 SetAPen(data->icld_BufferRastPort, data->icld_LabelShadowPen);
1544 Move(data->icld_BufferRastPort, tx + 1, ty + 1);
1545 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1546 offset_y = 1;
1547 case ICON_TEXTMODE_PLAIN:
1548 SetAPen(data->icld_BufferRastPort, data->icld_LabelPen);
1549 Move(data->icld_BufferRastPort, tx, ty);
1550 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1551 break;
1553 default:
1554 // Outline mode:
1555 SetSoftStyle(data->icld_BufferRastPort, FSF_BOLD, AskSoftStyle(data->icld_BufferRastPort));
1557 SetAPen(data->icld_BufferRastPort, data->icld_LabelShadowPen);
1558 Move(data->icld_BufferRastPort, tx + 1, ty );
1559 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1560 Move(data->icld_BufferRastPort, tx - 1, ty );
1561 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1562 Move(data->icld_BufferRastPort, tx, ty + 1);
1563 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1564 Move(data->icld_BufferRastPort, tx, ty - 1);
1565 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1567 SetAPen(data->icld_BufferRastPort, data->icld_LabelPen);
1568 Move(data->icld_BufferRastPort, tx , ty );
1569 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1571 SetSoftStyle(data->icld_BufferRastPort, FS_NORMAL, AskSoftStyle(data->icld_BufferRastPort));
1572 offset_y = 2;
1573 break;
1575 if ((curlabel_CurrentLine >= (curlabel_TotalLines -1)) && (curlabel_TotalLines < message->entry->ie_SplitParts))
1577 FreeVecPooled(data->icld_Pool, curlabel_StrPtr);
1579 ty = ty + offset_y;
1582 /*date/size sorting has the date/size appended under the message->entry label*/
1584 if ((message->entry->ie_IconListEntry.type != ST_USERDIR) && ((data->icld_SortFlags & (MUIV_IconList_Sort_BySize|MUIV_IconList_Sort_ByDate)) != 0))
1586 buf = NULL;
1587 SetFont(data->icld_BufferRastPort, data->icld_IconInfoFont);
1589 if (data->icld_SortFlags & MUIV_IconList_Sort_BySize)
1591 buf = message->entry->ie_TxtBuf_SIZE;
1592 txwidth = message->entry->ie_TxtBuf_SIZEWidth;
1594 else if (data->icld_SortFlags & MUIV_IconList_Sort_ByDate)
1596 if (message->entry->ie_Flags & ICONENTRY_FLAG_TODAY)
1598 buf = message->entry->ie_TxtBuf_TIME;
1599 txwidth = message->entry->ie_TxtBuf_TIMEWidth;
1601 else
1603 buf = message->entry->ie_TxtBuf_DATE;
1604 txwidth = message->entry->ie_TxtBuf_DATEWidth;
1608 if (buf)
1610 ULONG ie_LabelLength = strlen(buf);
1611 tx = labelX;
1613 if (txwidth < txtarea_width)
1614 tx += ((txtarea_width - txwidth)/2);
1616 ty = labelY + ((data->icld__Option_LabelTextVerticalPadding + data->icld_IconLabelFont->tf_YSize ) * curlabel_TotalLines) + data->icld_IconInfoFont->tf_YSize;
1618 switch ( data->icld__Option_LabelTextMode )
1620 case ICON_TEXTMODE_DROPSHADOW:
1621 SetAPen(data->icld_BufferRastPort, data->icld_InfoShadowPen);
1622 Move(data->icld_BufferRastPort, tx + 1, ty + 1); Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1623 case ICON_TEXTMODE_PLAIN:
1624 SetAPen(data->icld_BufferRastPort, data->icld_InfoPen);
1625 Move(data->icld_BufferRastPort, tx, ty); Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1626 break;
1628 default:
1629 // Outline mode..
1630 SetSoftStyle(data->icld_BufferRastPort, FSF_BOLD, AskSoftStyle(data->icld_BufferRastPort));
1631 SetAPen(data->icld_BufferRastPort, data->icld_InfoShadowPen);
1633 Move(data->icld_BufferRastPort, tx + 1, ty );
1634 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1635 Move(data->icld_BufferRastPort, tx - 1, ty );
1636 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1637 Move(data->icld_BufferRastPort, tx, ty - 1 );
1638 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1639 Move(data->icld_BufferRastPort, tx, ty + 1 );
1640 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1642 SetAPen(data->icld_BufferRastPort, data->icld_InfoPen);
1644 Move(data->icld_BufferRastPort, tx, ty );
1645 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1647 SetSoftStyle(data->icld_BufferRastPort, FS_NORMAL, AskSoftStyle(data->icld_BufferRastPort));
1648 break;
1654 return TRUE;
1657 /**************************************************************************
1659 **************************************************************************/
1660 ///IconList__MUIM_IconList_RethinkDimensions()
1661 IPTR IconList__MUIM_IconList_RethinkDimensions(struct IClass *CLASS, Object *obj, struct MUIP_IconList_RethinkDimensions *message)
1663 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1665 struct IconEntry *entry = NULL;
1666 LONG maxx = 0,
1667 maxy = 0;
1668 struct Rectangle icon_rect;
1670 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
1671 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1672 #endif
1674 if (message->singleicon != NULL)
1676 entry = message->singleicon;
1677 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1679 maxy = data->icld_LVMAttribs->lmva_RowHeight;
1680 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
1682 maxy += data->icld_LVMAttribs->lmva_HeaderHeight;
1685 else
1687 maxx = data->icld_AreaWidth - 1,
1688 maxy = data->icld_AreaHeight - 1;
1691 #if defined(DEBUG_ILC_ICONPOSITIONING)
1692 D(bug("[IconList] %s: SingleIcon - maxx = %d, maxy = %d\n", __PRETTY_FUNCTION__, maxx, maxy));
1693 #endif
1695 else
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 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1708 while (entry != NULL)
1710 if (entry->ie_DiskObj &&
1711 (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1713 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1715 maxy += data->icld_LVMAttribs->lmva_RowHeight;
1717 else
1719 IconList_GetIconAreaRectangle(obj, data, entry, &icon_rect);
1721 icon_rect.MaxX += entry->ie_IconX + data->icld__Option_IconHorizontalSpacing;
1722 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1723 (entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
1724 icon_rect.MaxX += (data->icld_IconAreaLargestWidth - entry->ie_AreaWidth);
1726 icon_rect.MaxY += entry->ie_IconY + data->icld__Option_IconVerticalSpacing;
1728 if (icon_rect.MaxX > maxx) maxx = icon_rect.MaxX;
1729 if (icon_rect.MaxY > maxy) maxy = icon_rect.MaxY;
1733 if (message->singleicon)
1734 break;
1736 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
1739 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1741 int col;
1743 for(col = 0; col < NUM_COLUMNS; col++)
1745 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[col];
1747 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
1749 maxx += data->icld_LVMAttribs->lmva_ColumnWidth[index];
1753 /* update our view when max x/y have changed */
1754 if (maxx + 1 != data->icld_AreaWidth)
1756 data->icld_AreaWidth = maxx + 1;
1757 SET(obj, MUIA_IconList_Width, data->icld_AreaWidth);
1759 if (maxy + 1 != data->icld_AreaHeight)
1761 data->icld_AreaHeight = maxy + 1;
1762 SET(obj, MUIA_IconList_Height, data->icld_AreaHeight);
1765 return TRUE;
1769 * This function executes the layouting when AutoSort is enabled. This means all icons are layouted regardless if
1770 * they have Provided position or not.
1773 static VOID IconList_Layout_FullAutoLayout(struct IClass *CLASS, Object *obj)
1775 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1776 struct IconEntry *entry = NULL;
1777 struct IconEntry *pass_first = NULL; /* First entry of current column or row */
1779 LONG left = data->icld__Option_IconHorizontalSpacing;
1780 LONG top = data->icld__Option_IconVerticalSpacing;
1781 LONG cur_x = left;
1782 LONG cur_y = top;
1783 LONG gridx = 0;
1784 LONG gridy = 0;
1785 LONG maxw = 0; /* Widest & talest entry in a column or row */
1786 LONG maxh = 0;
1788 BOOL calcnextpos;
1789 struct Rectangle iconrect;
1791 /* Now go to the actual positioning */
1792 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1793 while (entry != NULL)
1795 calcnextpos = FALSE;
1796 if ((entry->ie_DiskObj != NULL) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1798 calcnextpos = TRUE;
1800 /* Set previously calculated position to this icon */
1801 entry->ie_IconX = cur_x;
1802 entry->ie_IconY = cur_y;
1804 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
1806 if (data->icld_SelectionLastClicked == NULL) data->icld_SelectionLastClicked = entry;
1807 if (data->icld_FocusIcon == NULL) data->icld_FocusIcon = entry;
1810 /* Calculate grid size to advanced the coordinate in next step */
1811 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1813 maxw = data->icld_IconAreaLargestWidth + data->icld__Option_IconHorizontalSpacing;
1814 maxh = data->icld_IconLargestHeight + data->icld__Option_IconImageSpacing + data->icld_LabelLargestHeight + data->icld__Option_IconVerticalSpacing;
1815 gridx = maxw;
1816 gridy = maxh;
1818 else
1820 if (!(pass_first)) pass_first = entry;
1822 IconList_GetIconAreaRectangle(obj, data, entry, &iconrect);
1824 if ((maxw < entry->ie_AreaWidth) || (maxh < entry->ie_AreaHeight))
1826 if (maxw < entry->ie_AreaWidth) maxw = entry->ie_AreaWidth;
1827 if (maxh < entry->ie_AreaHeight) maxh = entry->ie_AreaHeight;
1828 if (pass_first != entry)
1830 entry = pass_first;
1831 cur_x = entry->ie_IconX;
1832 cur_y = entry->ie_IconY;
1833 /* We detected that the new icon it taller/wider than icons so far in this row/column.
1834 * We need to re-layout this row/column. */
1835 continue;
1839 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1841 /* Centering */
1842 if (entry->ie_AreaWidth < maxw)
1843 entry->ie_IconX += ( maxw - entry->ie_AreaWidth ) / 2;
1845 gridx = maxw;
1846 gridy = entry->ie_AreaHeight + data->icld__Option_IconVerticalSpacing;
1848 else
1850 /* Centering */ /* Icons look better not centered in this case - disabled */
1851 /* if (entry->ie_AreaHeight < maxh)
1852 entry->ie_IconY += ( maxh - entry->ie_AreaHeight ) / 2; */
1854 gridx = entry->ie_AreaWidth + data->icld__Option_IconHorizontalSpacing;
1855 gridy = maxh;
1861 * Advance to next icon and calculate its position based on grid sizes from previous step.
1862 * Don't set position - it is done at beginning of the loop.
1864 if ((entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode)) != NULL)
1866 if (calcnextpos)
1868 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1870 cur_y += gridy;
1872 if ((cur_y >= data->icld_ViewHeight) ||
1873 ((data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH) && ((cur_y + entry->ie_AreaHeight - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight)) ||
1874 ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) && ((cur_y + data->icld_IconAreaLargestHeight - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight)))
1876 /* Wrap "around" if the icon would be below bottom border */
1877 cur_x += maxw;
1878 cur_y = top;
1879 pass_first = NULL;
1880 maxw = 0;
1883 else
1885 cur_x += gridx;
1887 if ((cur_x >= data->icld_ViewWidth) ||
1888 ((data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH) && ((cur_x + entry->ie_AreaWidth - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth)) ||
1889 ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) && ((cur_x + data->icld_IconAreaLargestWidth - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth)))
1891 /* Wrap "around" if the icon would be right of right border */
1892 cur_x = left;
1893 cur_y += maxh;
1894 pass_first = NULL;
1895 maxh = 0;
1903 static VOID IconList_Layout_PartialAutoLayout(struct IClass *CLASS, Object *obj)
1905 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1906 struct Region *occupied = NewRegion();
1907 struct IconEntry *entry = NULL;
1908 LONG left = data->icld__Option_IconHorizontalSpacing;
1909 LONG top = data->icld__Option_IconVerticalSpacing;
1910 LONG cur_x = left, cur_y = top;
1912 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1913 while (entry != NULL)
1915 if ((entry->ie_ProvidedIconX != NO_ICON_POSITION) && (entry->ie_ProvidedIconY != NO_ICON_POSITION)
1916 && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1918 struct Rectangle iconrect = {
1919 entry->ie_ProvidedIconX,
1920 entry->ie_ProvidedIconY,
1921 entry->ie_ProvidedIconX + entry->ie_AreaWidth - 1,
1922 entry->ie_ProvidedIconY + entry->ie_AreaHeight - 1
1925 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1926 iconrect.MaxY += data->icld__Option_IconVerticalSpacing;
1927 else
1928 iconrect.MaxX += data->icld__Option_IconHorizontalSpacing;
1930 D(bug("Adding %s (%d %d)(%d %d)\n", entry->ie_TxtBuf_DisplayedLabel,
1931 (LONG)iconrect.MinX, (LONG)iconrect.MinY, (LONG)iconrect.MaxX, (LONG)iconrect.MaxY));
1933 OrRectRegion(occupied, &iconrect);
1935 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
1938 /* Now go to the actual positioning */
1939 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1940 while (entry != NULL)
1942 if ((entry->ie_DiskObj != NULL) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1944 if ((entry->ie_ProvidedIconX != NO_ICON_POSITION) && (entry->ie_ProvidedIconY != NO_ICON_POSITION))
1946 entry->ie_IconX = entry->ie_ProvidedIconX;
1947 entry->ie_IconY = entry->ie_ProvidedIconY;
1949 else
1951 LONG gridx, gridy, stepx, stepy, addx = 0;
1952 struct Rectangle iconarea;
1953 BOOL first = TRUE;
1955 /* Calculate grid size and step */
1956 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1958 gridx = data->icld_IconAreaLargestWidth + data->icld__Option_IconHorizontalSpacing;
1959 gridy = data->icld_IconLargestHeight + data->icld__Option_IconImageSpacing + data->icld_LabelLargestHeight + data->icld__Option_IconVerticalSpacing;
1960 stepx = gridx;
1961 stepy = gridy;
1963 else
1965 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1967 gridx = data->icld_IconAreaLargestWidth; /* This gives better centering effect */
1968 gridy = entry->ie_AreaHeight + data->icld__Option_IconVerticalSpacing;
1969 stepx = gridx;
1970 stepy = 2;
1971 addx = (gridx - entry->ie_AreaWidth) / 2;
1973 else
1975 gridx = entry->ie_AreaWidth + data->icld__Option_IconHorizontalSpacing;
1976 gridy = entry->ie_AreaHeight + data->icld__Option_IconVerticalSpacing;
1977 stepx = 2;
1978 stepy = gridy;
1982 /* Find first not occupied spot matching the calculate rectangle */
1985 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1987 /* Advance to next position */
1988 if (!first) cur_y += stepy;
1990 if ((cur_y >= data->icld_ViewHeight) ||
1991 ((cur_y + gridy - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight))
1993 /* Wrap "around" if the icon would be below bottom border */
1994 cur_x += stepx;
1995 cur_y = top;
1998 else
2000 /* Advance to next position */
2001 if (!first) cur_x += stepx;
2003 if ((cur_x >= data->icld_ViewWidth) ||
2004 ((cur_x + gridx - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth))
2006 /* Wrap "around" if the icon would be right of right border */
2007 cur_x = left;
2008 cur_y += stepy;
2012 iconarea.MinX = cur_x;
2013 iconarea.MinY = cur_y;
2014 iconarea.MaxX = cur_x + gridx - 1;
2015 iconarea.MaxY = cur_y + gridy - 1;
2017 first = FALSE;
2019 } while(RegionAndRect(occupied, &iconarea));
2021 entry->ie_IconX = iconarea.MinX + addx;
2022 entry->ie_IconY = iconarea.MinY;
2024 /* Add this area to occupied list */
2025 OrRectRegion(occupied, &iconarea);
2027 /* Add spacing to next icon */
2028 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
2029 cur_y += gridy;
2030 else
2031 cur_x += gridx;
2035 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
2038 DisposeRegion(occupied);
2042 ///IconList__MUIM_IconList_PositionIcons()
2043 /**************************************************************************
2044 MUIM_PositionIcons - Place icons with NO_ICON_POSITION coords somewhere
2045 **************************************************************************/
2046 IPTR IconList__MUIM_IconList_PositionIcons(struct IClass *CLASS, Object *obj, struct MUIP_IconList_PositionIcons *message)
2048 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2049 struct IconEntry *entry = NULL;
2052 #if defined(DEBUG_ILC_ICONPOSITIONING) || defined(DEBUG_ILC_FUNCS)
2053 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2054 #endif
2055 if ((data->icld_SortFlags & MUIV_IconList_Sort_AutoSort) == 0)
2057 IconList_Layout_PartialAutoLayout(CLASS, obj);
2059 else
2061 IconList_Layout_FullAutoLayout(CLASS, obj);
2065 * Set Provided icon position on all icons (this can't be done as part of previous loop!)
2066 * The icons will not no longer be autolayouted unless MUIV_IconList_Sort_AutoSort is set.
2067 * This give the stability that new icons appearing won't make existing icons jump from their places
2069 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
2070 while (entry != NULL)
2072 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
2073 DoMethod(obj, MUIM_IconList_PropagateEntryPos, entry);
2075 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
2079 DoMethod(obj, MUIM_IconList_RethinkDimensions, NULL);
2080 return (IPTR)NULL;
2084 ///OM_NEW()
2086 #define ICONENTRY_SIZE 16
2088 static inline void CalcHeight(struct ListViewModeAttribs *LVMAttribs, struct TextFont *LabelFont)
2090 ULONG YSize = LabelFont ? LabelFont->tf_YSize : 0;
2092 LVMAttribs->lmva_HeaderHeight = HEADERLINE_EXTRAHEIGHT + YSize;
2093 LVMAttribs->lmva_RowHeight = LINE_EXTRAHEIGHT + ((ICONENTRY_SIZE > YSize) ? ICONENTRY_SIZE : YSize);
2096 /**************************************************************************
2097 OM_NEW
2098 **************************************************************************/
2099 IPTR IconList__OM_NEW(struct IClass *CLASS, Object *obj, struct opSet *message)
2101 struct IconList_DATA *data = NULL;
2102 struct TextFont *icl_WindowFont = NULL;
2103 // struct RastPort *icl_RastPort = NULL;
2104 int i;
2106 #if defined(DEBUG_ILC_FUNCS)
2107 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2108 #endif
2110 icl_WindowFont = (struct TextFont *) GetTagData(MUIA_Font, (IPTR) NULL, message->ops_AttrList);
2112 obj = (Object *)DoSuperNewTags(CLASS, obj, NULL,
2113 MUIA_FillArea, FALSE,
2114 MUIA_Dropable, TRUE,
2115 MUIA_Font, MUIV_Font_Tiny,
2116 TAG_MORE, (IPTR) message->ops_AttrList);
2118 if (!obj) return FALSE;
2120 data = INST_DATA(CLASS, obj);
2122 data->icld_Pool = CreatePool(0,4096,4096);
2123 if (!data->icld_Pool)
2125 CoerceMethod(CLASS,obj,OM_DISPOSE);
2126 return (IPTR)NULL;
2129 #if defined(DEBUG_ILC_FUNCS)
2130 D(bug("[IconList] %s: SELF = 0x%p, muiRenderInfo = 0x%p\n", __PRETTY_FUNCTION__, obj, muiRenderInfo(obj)));
2131 #endif
2132 NewList((struct List*)&data->icld_IconList);
2133 NewList((struct List*)&data->icld_SelectionList);
2135 data->icld_IconLabelFont = icl_WindowFont;
2137 /* Setup Icon View-Mode options */
2138 data->icld_IVMAttribs = AllocMem(sizeof(struct IconViewModeAttribs), MEMF_CLEAR);
2139 /* Setup List View-Mode options */
2140 if ((data->icld_LVMAttribs = AllocMem(sizeof(struct ListViewModeAttribs), MEMF_CLEAR)) != NULL)
2142 for(i = 0; i < NUM_COLUMNS; i++)
2144 data->icld_LVMAttribs->lmva_ColumnPos[i] = i;
2145 data->icld_LVMAttribs->lmva_ColumnFlags[i] = LVMCF_COLVISIBLE;
2146 data->icld_LVMAttribs->lmva_ColumnWidth[i] = 100;
2147 data->icld_LVMAttribs->lmva_ColumnHAlign[i] = COLUMN_ALIGN_LEFT;
2148 switch (i)
2150 case INDEX_TYPE:
2151 data->icld_LVMAttribs->lmva_ColumnHAlign[i] = COLUMN_ALIGN_RIGHT;
2152 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= (LVMCF_COLCLICKABLE|LVMCF_COLSORTABLE);
2153 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Type";
2154 data->icld_LVMAttribs->lmva_ColumnWidth[i] = ICONENTRY_SIZE + 2;
2155 break;
2157 case INDEX_NAME:
2158 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= (LVMCF_COLCLICKABLE|LVMCF_COLSORTABLE);
2159 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Name";
2160 break;
2162 case INDEX_SIZE:
2163 data->icld_LVMAttribs->lmva_ColumnHAlign[i] = COLUMN_ALIGN_RIGHT;
2164 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= LVMCF_COLSORTABLE;
2165 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Size";
2166 break;
2168 case INDEX_LASTACCESS:
2169 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= LVMCF_COLSORTABLE;
2170 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Last Accessed";
2171 break;
2173 case INDEX_COMMENT:
2174 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Comment";
2175 break;
2177 case INDEX_PROTECTION:
2178 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Protection";
2179 break;
2181 default:
2182 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "<Unknown>";
2183 break;
2186 data->icld_LVMAttribs->lmva_LastSelectedColumn = -1;
2187 data->icld_LVMAttribs->lmva_SortColumn = INDEX_NAME;
2188 data->icld_LVMAttribs->lvma_Flags = LVMAF_HEADERDRAWTOEND;
2190 * Seems to be not needed because it's done in MUIM_Setup. No rendering happens before it.
2191 * Height calculation moved to MUIM_Setup because font pointer can be NULL here (if user-specified
2192 * font failed to open). In this case we fail back to the font specified in MUI's AreaData, but
2193 * it becomes known only in MUIM_Setup
2195 CalcHeight(data->icld_LVMAttribs, data->icld_IconLabelFont); */
2198 /* Get/Set initial values */
2199 /* TODO: TrimVolumeNames should be prefs settable */
2200 data->icld__Option_TrimVolumeNames = TRUE;
2201 /* TODO: Adjust overlap by window border width */
2202 data->icld__Option_IconBorderOverlap = 10;
2204 data->icld__Option_IconListMode = (UBYTE)GetTagData(MUIA_IconList_IconListMode, 0, message->ops_AttrList);
2205 data->icld__Option_LabelTextMode = (UBYTE)GetTagData(MUIA_IconList_LabelText_Mode, 0, message->ops_AttrList);
2206 data->icld__Option_LabelTextMaxLen = (ULONG)GetTagData(MUIA_IconList_LabelText_MaxLineLen, ILC_ICONLABEL_MAXLINELEN_DEFAULT, message->ops_AttrList);
2207 data->icld__Option_DragImageTransparent = (BOOL)GetTagData(MUIA_IconList_DragImageTransparent, FALSE, message->ops_AttrList);
2209 if ( data->icld__Option_LabelTextMaxLen < ILC_ICONLABEL_SHORTEST )
2210 data->icld__Option_LabelTextMaxLen = ILC_ICONLABEL_MAXLINELEN_DEFAULT;
2212 data->icld__Option_LastLabelTextMaxLen = data->icld__Option_LabelTextMaxLen;
2214 #if defined(DEBUG_ILC_FUNCS)
2215 D(bug("[IconList] %s: MaxLineLen : %ld\n", __PRETTY_FUNCTION__, data->icld__Option_LabelTextMaxLen));
2216 #endif
2217 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_NEWSIZE;
2218 data->ehn.ehn_Priority = 0;
2219 data->ehn.ehn_Flags = 0;
2220 data->ehn.ehn_Object = obj;
2221 data->ehn.ehn_Class = CLASS;
2223 data->icld_SortFlags = MUIV_IconList_Sort_ByName;
2224 data->icld_DisplayFlags = ICONLIST_DISP_SHOWINFO;
2226 __iconlist_UpdateLabels_hook.h_Entry = (HOOKFUNC)IconList__HookFunc_UpdateLabelsFunc;
2228 DoMethod
2230 obj, MUIM_Notify, MUIA_IconList_LabelText_MaxLineLen, MUIV_EveryTime,
2231 (IPTR)obj, 3,
2232 MUIM_CallHook, &__iconlist_UpdateLabels_hook, (IPTR)CLASS
2235 DoMethod
2237 obj, MUIM_Notify, MUIA_IconList_LabelText_MultiLine, MUIV_EveryTime,
2238 (IPTR)obj, 3,
2239 MUIM_CallHook, &__iconlist_UpdateLabels_hook, (IPTR)CLASS
2242 #if defined(DEBUG_ILC_FUNCS)
2243 D(bug("[IconList] obj = %ld\n", obj));
2244 #endif
2245 return (IPTR)obj;
2249 ///OM_DISPOSE()
2250 /**************************************************************************
2251 OM_DISPOSE
2252 **************************************************************************/
2253 IPTR IconList__OM_DISPOSE(struct IClass *CLASS, Object *obj, Msg message)
2255 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2256 struct IconEntry *node = NULL;
2258 #if defined(DEBUG_ILC_FUNCS)
2259 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2260 #endif
2262 #if defined(__AROS__)
2263 ForeachNode(&data->icld_IconList, node)
2264 #else
2265 Foreach_Node(&data->icld_IconList, node);
2266 #endif
2268 if (node->ie_DiskObj)
2269 FreeDiskObject(node->ie_DiskObj);
2272 if (data->icld_Pool) DeletePool(data->icld_Pool);
2274 DoSuperMethodA(CLASS,obj,message);
2275 return (IPTR)NULL;
2279 ///OM_SET()
2280 /**************************************************************************
2281 OM_SET
2282 **************************************************************************/
2283 IPTR IconList__OM_SET(struct IClass *CLASS, Object *obj, struct opSet *message)
2285 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2286 struct TagItem *tag = NULL,
2287 *tags = NULL;
2289 WORD oldleft = data->icld_ViewX,
2290 oldtop = data->icld_ViewY;
2291 //oldwidth = data->icld_ViewWidth,
2292 //oldheight = data->icld_ViewHeight;
2294 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ATTRIBS)
2295 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2296 #endif
2298 /* parse initial taglist */
2299 for (tags = message->ops_AttrList; (tag = NextTagItem((TAGITEM)&tags)); )
2301 switch (tag->ti_Tag)
2303 case MUIA_Virtgroup_Left:
2304 #if defined(DEBUG_ILC_ATTRIBS)
2305 D(bug("[IconList] %s: MUIA_Virtgroup_Left %ld\n", __PRETTY_FUNCTION__, tag->ti_Data));
2306 #endif
2307 if (data->icld_ViewX != tag->ti_Data)
2308 data->icld_ViewX = tag->ti_Data;
2309 break;
2311 case MUIA_Virtgroup_Top:
2312 #if defined(DEBUG_ILC_ATTRIBS)
2313 D(bug("[IconList] %s: MUIA_Virtgroup_Top %ld\n", __PRETTY_FUNCTION__, tag->ti_Data));
2314 #endif
2315 if (data->icld_ViewY != tag->ti_Data)
2316 data->icld_ViewY = tag->ti_Data;
2317 break;
2319 case MUIA_IconList_Rastport:
2320 #if defined(DEBUG_ILC_ATTRIBS)
2321 D(bug("[IconList] %s: MUIA_IconList_Rastport 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2322 #endif
2323 data->icld_DisplayRastPort = (struct RastPort*)tag->ti_Data;
2324 data->icld_DrawOffsetX = _mleft(obj);
2325 data->icld_DrawOffsetY = _mtop(obj);
2326 if (data->icld_BufferRastPort != NULL)
2328 //Buffer still set!?!?!
2330 SET(obj, MUIA_IconList_BufferRastport, tag->ti_Data);
2331 break;
2333 case MUIA_IconList_BufferRastport:
2334 #if defined(DEBUG_ILC_ATTRIBS)
2335 D(bug("[IconList] %s: MUIA_IconList_BufferRastport 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2336 #endif
2337 data->icld_BufferRastPort = (struct RastPort*)tag->ti_Data;
2338 break;
2340 case MUIA_Font:
2341 #if defined(DEBUG_ILC_ATTRIBS)
2342 D(bug("[IconList] %s: MUIA_Font 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2343 #endif
2344 data->icld_IconLabelFont = (struct TextFont*)tag->ti_Data;
2345 /* FIXME: Should we call CalcHeight() here because our font changed? */
2346 break;
2348 case MUIA_IconList_LabelInfoText_Font:
2349 #if defined(DEBUG_ILC_ATTRIBS)
2350 D(bug("[IconList] %s: MUIA_IconList_LabelInfoText_Font 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2351 #endif
2352 data->icld_IconInfoFont = (struct TextFont*)tag->ti_Data;
2353 break;
2355 case MUIA_IconList_DisplayFlags:
2357 #if defined(DEBUG_ILC_ATTRIBS)
2358 D(bug("[IconList] %s: MUIA_IconList_DisplayFlags %08x\n", __PRETTY_FUNCTION__, tag->ti_Data));
2359 #endif
2360 // ULONG origModeFlags = data->icld_DisplayFlags & (ICONLIST_DISP_MODEDEFAULT|ICONLIST_DISP_MODELABELRIGHT|ICONLIST_DISP_MODELIST);
2361 data->icld_DisplayFlags = (ULONG)tag->ti_Data;
2363 if (data->icld_DisplayFlags & ICONLIST_DISP_BUFFERED)
2365 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2366 D(bug("[IconList] %s: MUIA_IconList_DisplayFlags & ICONLIST_DISP_BUFFERED\n", __PRETTY_FUNCTION__));
2367 #endif
2368 if ((data->icld_BufferRastPort != NULL)
2369 && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
2371 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2372 D(bug("[IconList] %s: BackLayer @ %p for BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
2373 #endif
2374 if ((GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_WIDTH) != data->icld_ViewWidth)
2375 || (GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_HEIGHT) != data->icld_ViewHeight))
2377 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
2378 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2379 D(bug("[IconList] %s: Destroying old BackLayer\n", __PRETTY_FUNCTION__));
2380 #endif
2381 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2382 DeleteLayer(0, oldLayer);
2386 if ((data->icld_BufferRastPort == NULL) || (data->icld_BufferRastPort == data->icld_DisplayRastPort))
2388 struct BitMap *bitmap_New = NULL;
2389 ULONG tmp_RastDepth;
2390 struct Layer_Info *li = NULL;
2392 tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
2393 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
2394 data->icld_ViewHeight,
2395 tmp_RastDepth,
2396 BMF_CLEAR,
2397 data->icld_DisplayRastPort->BitMap))!=NULL)
2399 if ((data->icld_BufferRastPort = CreateRastPort())!=NULL)
2401 data->icld_BufferRastPort->BitMap = bitmap_New;
2402 if ((li = NewLayerInfo()))
2404 if ((data->icld_BufferRastPort->Layer = CreateUpfrontLayer(li, data->icld_BufferRastPort->BitMap, 0, 0, data->icld_ViewWidth - 1, data->icld_ViewHeight - 1, 0, NULL)))
2407 * Mark it as a buffered rastport.
2410 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2411 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
2412 #endif
2413 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
2414 data->icld_DrawOffsetX = 0;
2415 data->icld_DrawOffsetY = 0;
2417 else
2418 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2420 else
2421 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2423 else
2424 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2426 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
2428 if (bitmap_New) FreeBitMap(bitmap_New);
2429 if (li) DisposeLayerInfo(li);
2430 data->icld_DrawOffsetX = _mleft(obj);
2431 data->icld_DrawOffsetY = _mtop(obj);
2435 else
2437 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
2439 //Free up the buffers layer, rastport and bitmap since they are no longer needed ..
2440 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
2441 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2442 InstallClipRegion(oldLayer, NULL);
2443 DeleteLayer(0, oldLayer);
2444 FreeBitMap(data->icld_BufferRastPort->BitMap);
2445 data->icld_DrawOffsetX = _mleft(obj);
2446 data->icld_DrawOffsetY = _mtop(obj);
2449 SET(obj, MUIA_IconList_Changed, TRUE);
2451 break;
2453 case MUIA_IconList_SortFlags:
2454 #if defined(DEBUG_ILC_ATTRIBS)
2455 D(bug("[IconList] %s: MUIA_IconList_SortFlags %08x\n", __PRETTY_FUNCTION__, tag->ti_Data));
2456 #endif
2457 data->icld_SortFlags = (ULONG)tag->ti_Data;
2458 break;
2460 case MUIA_IconList_DragImageTransparent:
2461 data->icld__Option_DragImageTransparent = (BOOL)tag->ti_Data;
2462 break;
2464 case MUIA_IconList_IconListMode:
2465 #if defined(DEBUG_ILC_ATTRIBS)
2466 D(bug("[IconList] %s: MUIA_IconList_IconListMode %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2467 #endif
2468 data->icld__Option_IconListMode = (UBYTE)tag->ti_Data;
2469 break;
2471 case MUIA_IconList_LabelText_Mode:
2472 #if defined(DEBUG_ILC_ATTRIBS)
2473 D(bug("[IconList] %s: MUIA_IconList_LabelText_Mode %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2474 #endif
2475 data->icld__Option_LabelTextMode = (UBYTE)tag->ti_Data;
2476 break;
2478 case MUIA_IconList_LabelText_MaxLineLen:
2479 #if defined(DEBUG_ILC_ATTRIBS)
2480 D(bug("[IconList] %s: MUIA_IconList_LabelText_MaxLineLen %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2481 #endif
2482 if (tag->ti_Data >= ILC_ICONLABEL_SHORTEST)
2484 data->icld__Option_LabelTextMaxLen = (ULONG)tag->ti_Data;
2486 else
2488 data->icld__Option_LabelTextMaxLen = ILC_ICONLABEL_MAXLINELEN_DEFAULT;
2490 break;
2492 case MUIA_IconList_LabelText_MultiLine:
2493 #if defined(DEBUG_ILC_ATTRIBS)
2494 D(bug("[IconList] %s: MUIA_IconList_LabelText_MultiLine %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2495 #endif
2496 data->icld__Option_LabelTextMultiLine = (ULONG)tag->ti_Data;
2497 if (data->icld__Option_LabelTextMultiLine == 0)data->icld__Option_LabelTextMultiLine = 1;
2498 break;
2500 case MUIA_IconList_LabelText_MultiLineOnFocus:
2501 #if defined(DEBUG_ILC_ATTRIBS)
2502 D(bug("[IconList] %s: MUIA_IconList_LabelText_MultiLineOnFocus %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2503 #endif
2504 data->icld__Option_LabelTextMultiLineOnFocus = (BOOL)tag->ti_Data;
2505 break;
2507 case MUIA_IconList_Icon_HorizontalSpacing:
2508 #if defined(DEBUG_ILC_ATTRIBS)
2509 D(bug("[IconList] %s: MUIA_IconList_Icon_HorizontalSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2510 #endif
2511 data->icld__Option_IconHorizontalSpacing = (UBYTE)tag->ti_Data;
2512 break;
2514 case MUIA_IconList_Icon_VerticalSpacing:
2515 #if defined(DEBUG_ILC_ATTRIBS)
2516 D(bug("[IconList] %s: MUIA_IconList_Icon_VerticalSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2517 #endif
2518 data->icld__Option_IconVerticalSpacing = (UBYTE)tag->ti_Data;
2519 break;
2521 case MUIA_IconList_Icon_ImageSpacing:
2522 #if defined(DEBUG_ILC_ATTRIBS)
2523 D(bug("[IconList] %s: MUIA_IconList_Icon_ImageSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2524 #endif
2525 data->icld__Option_IconImageSpacing = (UBYTE)tag->ti_Data;
2526 break;
2528 case MUIA_IconList_LabelText_HorizontalPadding:
2529 #if defined(DEBUG_ILC_ATTRIBS)
2530 D(bug("[IconList] %s: MUIA_IconList_LabelText_HorizontalPadding %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2531 #endif
2532 data->icld__Option_LabelTextHorizontalPadding = (UBYTE)tag->ti_Data;
2533 break;
2535 case MUIA_IconList_LabelText_VerticalPadding:
2536 #if defined(DEBUG_ILC_ATTRIBS)
2537 D(bug("[IconList] %s: MUIA_IconList_LabelText_VerticalPadding %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2538 #endif
2539 data->icld__Option_LabelTextVerticalPadding = (UBYTE)tag->ti_Data;
2540 break;
2542 case MUIA_IconList_LabelText_BorderWidth:
2543 #if defined(DEBUG_ILC_ATTRIBS)
2544 D(bug("[IconList] %s: MUIA_IconList_LabelText_BorderWidth %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2545 #endif
2546 data->icld__Option_LabelTextBorderWidth = (UBYTE)tag->ti_Data;
2547 break;
2549 case MUIA_IconList_LabelText_BorderHeight:
2550 #if defined(DEBUG_ILC_ATTRIBS)
2551 D(bug("[IconList] %s: MUIA_IconList_LabelText_BorderHeight %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2552 #endif
2553 data->icld__Option_LabelTextBorderHeight = (UBYTE)tag->ti_Data;
2554 break;
2556 case MUIA_IconList_LabelText_Pen:
2557 data->icld_LabelPen = (ULONG)tag->ti_Data;
2558 break;
2560 case MUIA_IconList_LabelText_ShadowPen:
2561 data->icld_LabelShadowPen = (ULONG)tag->ti_Data;
2562 break;
2564 case MUIA_IconList_LabelInfoText_Pen:
2565 data->icld_InfoPen = (ULONG)tag->ti_Data;
2566 break;
2568 case MUIA_IconList_LabelInfoText_ShadowPen:
2569 data->icld_InfoShadowPen = (ULONG)tag->ti_Data;
2570 break;
2572 /* Settings defined by the view class */
2573 case MUIA_IconListview_FixedBackground:
2574 #if defined(DEBUG_ILC_ATTRIBS)
2575 D(bug("[IconList] %s: MUIA_IconListview_FixedBackground\n", __PRETTY_FUNCTION__));
2576 #endif
2577 data->icld__Option_IconListFixedBackground = (BOOL)tag->ti_Data;
2578 break;
2580 case MUIA_IconListview_ScaledBackground:
2581 #if defined(DEBUG_ILC_ATTRIBS)
2582 D(bug("[IconList] %s: MUIA_IconListview_ScaledBackground\n", __PRETTY_FUNCTION__));
2583 #endif
2584 data->icld__Option_IconListScaledBackground = (BOOL)tag->ti_Data;
2585 break;
2587 /* We listen for MUIA_Background and set default values for known types */
2588 case MUIA_Background:
2589 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2590 D(bug("[IconList] %s: MUIA_Background\n", __PRETTY_FUNCTION__));
2591 #endif
2593 char *bgmode_string = (char *)tag->ti_Data;
2594 BYTE this_mode = bgmode_string[0] - 48;
2596 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2597 D(bug("[IconList] %s: MUIA_Background | MUI BG Mode = %d\n", __PRETTY_FUNCTION__, this_mode));
2598 #endif
2599 switch (this_mode)
2601 case 0:
2602 //MUI Pattern
2603 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2604 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2605 break;
2606 case 2:
2607 //MUI RGB color
2608 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2609 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2610 break;
2611 case 7:
2612 //Zune Gradient
2613 NNSET(obj, MUIA_IconListview_FixedBackground, TRUE);
2614 NNSET(obj, MUIA_IconListview_ScaledBackground, TRUE);
2615 break;
2616 case 5:
2617 //Image
2618 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2619 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2620 break;
2623 break;
2624 case MUIA_IconList_IconsDropped:
2625 data->icld_DragDropEvent = (struct IconList_Drop_Event *)tag->ti_Data;
2626 break;
2630 #if defined(DEBUG_ILC_ATTRIBS)
2631 D(bug("[IconList] %s(), out of switch\n", __PRETTY_FUNCTION__));
2632 #endif
2633 if ((oldleft != data->icld_ViewX) || (oldtop != data->icld_ViewY))
2635 data->icld_UpdateMode = UPDATE_SCROLL;
2636 data->update_scrolldx = data->icld_ViewX - oldleft;
2637 data->update_scrolldy = data->icld_ViewY - oldtop;
2638 #if defined(DEBUG_ILC_ATTRIBS)
2639 D(bug("[IconList] %s(), call MUI_Redraw()\n", __PRETTY_FUNCTION__));
2640 #endif
2641 MUI_Redraw(obj, MADF_DRAWUPDATE);
2644 #if defined(DEBUG_ILC_ATTRIBS)
2645 D(bug("[IconList] %s(), call DoSuperMethodA()\n", __PRETTY_FUNCTION__));
2646 #endif
2647 return DoSuperMethodA(CLASS, obj, (Msg)message);
2651 ///OM_GET()
2652 /**************************************************************************
2653 OM_GET
2654 **************************************************************************/
2655 IPTR IconList__OM_GET(struct IClass *CLASS, Object *obj, struct opGet *message)
2657 /* small macro to simplify return value storage */
2658 #define STORE *(message->opg_Storage)
2659 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2661 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ATTRIBS)
2662 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2663 #endif
2665 switch (message->opg_AttrID)
2667 case MUIA_IconList_Rastport: STORE = (IPTR)data->icld_DisplayRastPort; return 1;
2668 case MUIA_IconList_BufferRastport: STORE = (IPTR)data->icld_BufferRastPort; return 1;
2669 case MUIA_IconList_BufferLeft: STORE = (IPTR)data->icld_DrawOffsetX; return 1;
2670 case MUIA_IconList_BufferTop: STORE = (IPTR)data->icld_DrawOffsetY; return 1;
2671 case MUIA_IconList_BufferWidth:
2672 case MUIA_IconList_Width: STORE = (IPTR)data->icld_AreaWidth; return 1;
2673 case MUIA_IconList_BufferHeight:
2674 case MUIA_IconList_Height: STORE = (IPTR)data->icld_AreaHeight; return 1;
2675 case MUIA_IconList_IconsDropped: STORE = (IPTR)data->icld_DragDropEvent; return 1;
2676 case MUIA_IconList_Clicked: STORE = (IPTR)&data->icld_ClickEvent; return 1;
2677 case MUIA_IconList_IconListMode: STORE = (IPTR)data->icld__Option_IconListMode; return 1;
2678 case MUIA_IconList_LabelText_Mode: STORE = (IPTR)data->icld__Option_LabelTextMode; return 1;
2679 case MUIA_IconList_LabelText_MaxLineLen: STORE = (IPTR)data->icld__Option_LabelTextMaxLen; return 1;
2680 case MUIA_IconList_LabelText_MultiLine: STORE = (IPTR)data->icld__Option_LabelTextMultiLine; return 1;
2681 case MUIA_IconList_LabelText_MultiLineOnFocus: STORE = (IPTR)data->icld__Option_LabelTextMultiLineOnFocus; return 1;
2682 case MUIA_IconList_DisplayFlags: STORE = (IPTR)data->icld_DisplayFlags; return 1;
2683 case MUIA_IconList_SortFlags: STORE = (IPTR)data->icld_SortFlags; return 1;
2685 case MUIA_IconList_FocusIcon: STORE = (IPTR)data->icld_FocusIcon; return 1;
2687 case MUIA_Font: STORE = (IPTR)data->icld_IconLabelFont; return 1;
2688 case MUIA_IconList_LabelText_Pen: STORE = (IPTR)data->icld_LabelPen; return 1;
2689 case MUIA_IconList_LabelText_ShadowPen: STORE = (IPTR)data->icld_LabelShadowPen; return 1;
2690 case MUIA_IconList_LabelInfoText_Font: STORE = (IPTR)data->icld_IconInfoFont; return 1;
2691 case MUIA_IconList_LabelInfoText_Pen: STORE = (IPTR)data->icld_InfoPen; return 1;
2692 case MUIA_IconList_LabelInfoText_ShadowPen: STORE = (IPTR)data->icld_InfoShadowPen; return 1;
2693 case MUIA_IconList_DragImageTransparent: STORE = (IPTR)data->icld__Option_DragImageTransparent; return 1;
2695 case MUIA_IconList_Icon_HorizontalSpacing: STORE = (IPTR)data->icld__Option_IconHorizontalSpacing; return 1;
2696 case MUIA_IconList_Icon_VerticalSpacing: STORE = (IPTR)data->icld__Option_IconVerticalSpacing; return 1;
2697 case MUIA_IconList_Icon_ImageSpacing: STORE = (IPTR)data->icld__Option_IconImageSpacing; return 1;
2698 case MUIA_IconList_LabelText_HorizontalPadding: STORE = (IPTR)data->icld__Option_LabelTextHorizontalPadding; return 1;
2699 case MUIA_IconList_LabelText_VerticalPadding: STORE = (IPTR)data->icld__Option_LabelTextVerticalPadding; return 1;
2700 case MUIA_IconList_LabelText_BorderWidth: STORE = (IPTR)data->icld__Option_LabelTextBorderWidth; return 1;
2701 case MUIA_IconList_LabelText_BorderHeight: STORE = (IPTR)data->icld__Option_LabelTextBorderHeight; return 1;
2703 /* Settings defined by the view class */
2704 case MUIA_IconListview_FixedBackground: STORE = (IPTR)data->icld__Option_IconListFixedBackground; return 1;
2705 case MUIA_IconListview_ScaledBackground: STORE = (IPTR)data->icld__Option_IconListScaledBackground; return 1;
2707 /* ICON obj Changes */
2708 case MUIA_Virtgroup_Left: STORE = (IPTR)data->icld_ViewX; return 1;
2709 case MUIA_Virtgroup_Top: STORE = (IPTR)data->icld_ViewY; return 1;
2710 case MUIA_Family_List: STORE = (IPTR)&(data->icld_IconList); return 1; /* Get our list object */
2712 /* TODO: Get the version/revision from our config.. */
2713 case MUIA_Version: STORE = (IPTR)1; return 1;
2714 case MUIA_Revision: STORE = (IPTR)7; return 1;
2717 return DoSuperMethodA(CLASS, obj, (Msg) message);
2718 #undef STORE
2722 IPTR IconList__MUIM_Family_AddHead(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddHead *message)
2724 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2725 #if defined(DEBUG_ILC_FUNCS)
2726 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2727 #endif
2729 if (message->obj)
2731 /* TODO: Use the correct _OBJECT() code when we switch to icon.mui */
2732 // AddHead(&(data->icld_IconList), (struct Node *)_OBJECT(message->obj));
2733 AddHead(&(data->icld_IconList), (struct Node *)message->obj);
2734 return TRUE;
2736 else
2737 return FALSE;
2740 IPTR IconList__MUIM_Family_AddTail(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddTail *message)
2742 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2743 #if defined(DEBUG_ILC_FUNCS)
2744 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2745 #endif
2747 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));
2749 if (message->obj)
2751 /* TODO: Use the correct _OBJECT() code when we switch to icon.mui */
2752 // AddTail(&(data->icld_IconList), (struct Node *)_OBJECT(message->obj));
2753 AddTail(&(data->icld_IconList), (struct Node *)message->obj);
2754 return TRUE;
2756 else
2757 return FALSE;
2759 return (IPTR)NULL;
2761 #if !defined(WANDERER_BUILTIN_ICONLIST)
2762 IPTR IconList__OM_ADDMEMBER(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddTail *message)
2764 return IconList__MUIM_Family_AddTail(CLASS, obj, message);
2766 #endif
2768 IPTR IconList__MUIM_Family_Remove(struct IClass *CLASS, Object *obj, struct MUIP_Family_Remove *message)
2770 // struct IconList_DATA *data = INST_DATA(CLASS, obj);
2771 #if defined(DEBUG_ILC_FUNCS)
2772 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2773 #endif
2775 D(bug("[IconList] %s: entry @ 0x%p '%s'\n", __PRETTY_FUNCTION__, message->obj, ((struct IconEntry *)message->obj)->ie_IconNode.ln_Name));
2777 if (message->obj)
2779 /* TODO: Use the correct _OBJECT() code when we switch to icon.mui */
2780 // Remove((struct Node *)_OBJECT(message->obj));
2781 Remove((struct Node *)message->obj);
2782 return TRUE;
2784 else
2785 return FALSE;
2787 return (IPTR)NULL;
2789 #if !defined(WANDERER_BUILTIN_ICONLIST)
2790 IPTR IconList__OM_REMMEMBER(struct IClass *CLASS, Object *obj, struct MUIP_Family_Remove *message)
2792 return IconList__MUIM_Family_Remove(CLASS, obj, message);
2794 #endif
2796 ///MUIM_Setup()
2797 /**************************************************************************
2798 MUIM_Setup
2799 **************************************************************************/
2800 IPTR IconList__MUIM_Setup(struct IClass *CLASS, Object *obj, struct MUIP_Setup *message)
2802 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2803 struct IconEntry *node = NULL;
2804 IPTR geticon_error = 0, iconlistScreen;
2806 #if defined(DEBUG_ILC_FUNCS)
2807 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2808 #endif
2810 if (!DoSuperMethodA(CLASS, obj, (Msg) message)) return (IPTR)NULL;
2812 iconlistScreen = (IPTR)_screen(obj);
2813 #if defined(DEBUG_ILC_ICONRENDERING)
2814 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
2815 #endif
2817 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
2819 /* Get Internal Objects to use if not set .. */
2820 data->icld_DisplayRastPort = NULL;
2821 data->icld_BufferRastPort = NULL;
2823 if (data->icld_IconLabelFont == NULL) data->icld_IconLabelFont = _font(obj);
2824 if (data->icld_IconInfoFont == NULL) data->icld_IconInfoFont = data->icld_IconLabelFont;
2827 * Here we have our font, either from user preferences or from MUI's AreaData.
2828 * It's right time to set up some sizes.
2830 CalcHeight(data->icld_LVMAttribs, data->icld_IconLabelFont);
2831 #if defined(DEBUG_ILC_ICONRENDERING)
2832 D(bug("[IconList] %s: Use Font @ 0x%p, RastPort @ 0x%p\n", __PRETTY_FUNCTION__, data->icld_IconLabelFont, data->icld_BufferRastPort ));
2833 #endif
2835 /* Set our base options .. */
2836 data->icld_LabelPen = _pens(obj)[MPEN_SHINE];
2837 data->icld_LabelShadowPen = _pens(obj)[MPEN_SHADOW];
2838 data->icld_InfoPen = _pens(obj)[MPEN_SHINE];
2839 data->icld_InfoShadowPen = _pens(obj)[MPEN_SHADOW];
2841 data->icld__Option_LabelTextMultiLine = 1;
2842 data->icld__Option_LastLabelTextMultiLine = data->icld__Option_LabelTextMultiLine;
2844 data->icld__Option_LabelTextMultiLineOnFocus = FALSE;
2846 data->icld__Option_IconHorizontalSpacing = ILC_ICON_HORIZONTALMARGIN_DEFAULT;
2847 data->icld__Option_IconVerticalSpacing = ILC_ICON_VERTICALMARGIN_DEFAULT;
2848 data->icld__Option_IconImageSpacing = ILC_ICONLABEL_IMAGEMARGIN_DEFAULT;
2849 data->icld__Option_LabelTextHorizontalPadding = ILC_ICONLABEL_HORIZONTALTEXTMARGIN_DEFAULT;
2850 data->icld__Option_LabelTextVerticalPadding = ILC_ICONLABEL_VERTICALTEXTMARGIN_DEFAULT;
2851 data->icld__Option_LabelTextBorderWidth = ILC_ICONLABEL_BORDERWIDTH_DEFAULT;
2852 data->icld__Option_LabelTextBorderHeight = ILC_ICONLABEL_BORDERHEIGHT_DEFAULT;
2854 if (data->icld_LVMAttribs)
2856 data->icld_LVMAttribs->lvma_IconDrawer = GetIconTags
2858 "WANDERER:Icons/drawer",
2859 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
2860 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
2861 ICONGETA_FailIfUnavailable, TRUE,
2862 ICONGETA_GenerateImageMasks, TRUE,
2863 ICONA_ErrorCode, &geticon_error,
2864 TAG_DONE
2867 #if defined(DEBUG_ILC_ICONRENDERING)
2868 if (data->icld_LVMAttribs->lvma_IconDrawer == NULL)
2870 D(bug("[IconList] %s: Couldnt get drawer DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
2872 #endif
2873 data->icld_LVMAttribs->lvma_IconFile = GetIconTags
2875 "WANDERER:Icons/file",
2876 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
2877 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
2878 ICONGETA_FailIfUnavailable, TRUE,
2879 ICONGETA_GenerateImageMasks, TRUE,
2880 ICONA_ErrorCode, &geticon_error,
2881 TAG_DONE
2884 #if defined(DEBUG_ILC_ICONRENDERING)
2885 if (data->icld_LVMAttribs->lvma_IconFile == NULL)
2887 D(bug("[IconList] %s: Couldnt get file DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
2889 #endif
2892 #if defined(__AROS__)
2893 ForeachNode(&data->icld_IconList, node)
2894 #else
2895 Foreach_Node(&data->icld_IconList, node);
2896 #endif
2898 if (!node->ie_DiskObj)
2900 if (!(node->ie_DiskObj = GetIconTags(node->ie_IconNode.ln_Name,
2901 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
2902 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
2903 ICONGETA_GenerateImageMasks, TRUE,
2904 ICONGETA_FailIfUnavailable, FALSE,
2905 ICONA_ErrorCode, &geticon_error,
2906 TAG_DONE)))
2908 #if defined(DEBUG_ILC_ICONRENDERING)
2909 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));
2910 #endif
2911 /* We should probably remove this node if the entry cant be obtained ? */
2915 return 1;
2919 ///MUIM_Show()
2920 /**************************************************************************
2921 MUIM_Show
2922 **************************************************************************/
2923 IPTR IconList__MUIM_Show(struct IClass *CLASS, Object *obj, struct MUIP_Show *message)
2925 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2926 LONG newleft,
2927 newtop;
2928 IPTR rc;
2930 #if defined(DEBUG_ILC_FUNCS)
2931 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2932 #endif
2934 if ((rc = DoSuperMethodA(CLASS, obj, (Msg)message)))
2936 newleft = data->icld_ViewX;
2937 newtop = data->icld_ViewY;
2939 if (newleft + _mwidth(obj) > data->icld_AreaWidth)
2940 newleft = data->icld_AreaWidth - _mwidth(obj);
2941 if (newleft < 0)
2942 newleft = 0;
2944 if (newtop + _mheight(obj) > data->icld_AreaHeight)
2945 newtop = data->icld_AreaHeight - _mheight(obj);
2946 if (newtop < 0)
2947 newtop = 0;
2949 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
2951 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
2952 MUIA_Virtgroup_Top, newtop,
2953 TAG_DONE);
2956 /* Get Internal Objects to use if not set .. */
2957 if (data->icld_DisplayRastPort == NULL)
2959 if (_rp(obj) != NULL)
2961 data->icld_DisplayRastPort = CloneRastPort(_rp(obj));
2963 #if defined(DEBUG_ILC_ICONRENDERING)
2964 else
2966 D(bug("[IconList] IconList__MUIM_Show: ERROR - NULL RastPort!\n"));
2968 #endif
2971 if (data->icld_DisplayFlags & ICONLIST_DISP_BUFFERED)
2973 struct BitMap *bitmap_New = NULL;
2974 struct Layer_Info *li = NULL;
2976 ULONG tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
2977 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
2978 data->icld_ViewHeight,
2979 tmp_RastDepth,
2980 BMF_CLEAR,
2981 data->icld_DisplayRastPort->BitMap))!=NULL)
2983 if ((data->icld_BufferRastPort = CreateRastPort())!=NULL)
2985 data->icld_BufferRastPort->BitMap = bitmap_New;
2986 if ((li = NewLayerInfo()))
2988 if ((data->icld_BufferRastPort->Layer = CreateUpfrontLayer(li, data->icld_BufferRastPort->BitMap, 0, 0, data->icld_ViewWidth - 1, data->icld_ViewHeight - 1, 0, NULL)))
2991 * Mark it as a buffered rastport.
2994 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
2995 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
2996 #endif
2997 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
2998 data->icld_DrawOffsetX = 0;
2999 data->icld_DrawOffsetY = 0;
3001 else
3002 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3004 else
3005 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3007 else
3008 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3010 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
3012 if (bitmap_New) FreeBitMap(bitmap_New);
3013 if (li) DisposeLayerInfo(li);
3014 data->icld_DrawOffsetX = _mleft(obj);
3015 data->icld_DrawOffsetY = _mtop(obj);
3018 else
3020 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3021 data->icld_DrawOffsetX = _mleft(obj);
3022 data->icld_DrawOffsetY = _mtop(obj);
3025 if (data->icld_IconLabelFont == NULL) data->icld_IconLabelFont = _font(obj);
3026 if (data->icld_IconInfoFont == NULL) data->icld_IconInfoFont = data->icld_IconLabelFont;
3027 #if defined(DEBUG_ILC_ICONRENDERING)
3028 D(bug("[IconList] IconList__MUIM_Show: Use Font @ 0x%p, RastPort @ 0x%p\n", data->icld_IconLabelFont, data->icld_BufferRastPort ));
3029 #endif
3031 if ((data->icld_BufferRastPort) && (data->icld_IconLabelFont))
3032 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
3034 return rc;
3038 ///MUIM_Hide()
3039 /**************************************************************************
3040 MUIM_Hide
3041 **************************************************************************/
3042 IPTR IconList__MUIM_Hide(struct IClass *CLASS, Object *obj, struct MUIP_Hide *message)
3044 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3045 IPTR rc;
3047 #if defined(DEBUG_ILC_FUNCS)
3048 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3049 #endif
3051 if ((rc = DoSuperMethodA(CLASS, obj, (Msg)message)))
3053 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
3055 DeleteLayer(0, data->icld_BufferRastPort->Layer);
3058 data->icld_BufferRastPort = NULL;
3060 if (data->icld_DisplayRastPort)
3061 FreeRastPort(data->icld_DisplayRastPort);
3063 data->icld_DisplayRastPort = NULL;
3065 return rc;
3069 ///MUIM_Cleanup()
3070 /**************************************************************************
3071 MUIM_Cleanup
3072 **************************************************************************/
3073 IPTR IconList__MUIM_Cleanup(struct IClass *CLASS, Object *obj, struct MUIP_Cleanup *message)
3075 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3076 struct IconEntry *node = NULL;
3078 #if defined(DEBUG_ILC_FUNCS)
3079 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3080 #endif
3082 #if defined(__AROS__)
3083 ForeachNode(&data->icld_IconList, node)
3084 #else
3085 Foreach_Node(&data->icld_IconList, node);
3086 #endif
3088 if (node->ie_DiskObj)
3090 FreeDiskObject(node->ie_DiskObj);
3091 node->ie_DiskObj = NULL;
3095 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
3097 return DoSuperMethodA(CLASS, obj, (Msg)message);
3101 ///MUIM_AskMinMax()
3102 /**************************************************************************
3103 MUIM_AskMinMax
3104 **************************************************************************/
3105 IPTR IconList__MUIM_AskMinMax(struct IClass *CLASS, Object *obj, struct MUIP_AskMinMax *message)
3107 ULONG rc = DoSuperMethodA(CLASS, obj, (Msg) message);
3109 #if defined(DEBUG_ILC_FUNCS)
3110 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3111 #endif
3113 message->MinMaxInfo->MinWidth += 96;
3114 message->MinMaxInfo->MinHeight += 64;
3116 message->MinMaxInfo->DefWidth += 200;
3117 message->MinMaxInfo->DefHeight += 180;
3119 message->MinMaxInfo->MaxWidth = MUI_MAXMAX;
3120 message->MinMaxInfo->MaxHeight = MUI_MAXMAX;
3122 return rc;
3126 ///MUIM_Layout()
3127 /**************************************************************************
3128 MUIM_Layout
3129 **************************************************************************/
3130 IPTR IconList__MUIM_Layout(struct IClass *CLASS, Object *obj,struct MUIP_Layout *message)
3132 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3133 ULONG rc;
3135 #if defined(DEBUG_ILC_FUNCS)
3136 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3137 #endif
3139 rc = DoSuperMethodA(CLASS, obj, (Msg)message);
3141 data->icld_ViewWidth = _mwidth(obj);
3142 data->icld_ViewHeight = _mheight(obj);
3144 return rc;
3148 static LONG FirstVisibleLine(struct IconList_DATA *data)
3150 return data->icld_ViewY / data->icld_LVMAttribs->lmva_RowHeight;
3153 static LONG NumVisibleLines(struct IconList_DATA *data)
3155 LONG visible = data->icld_ViewHeight + data->icld_LVMAttribs->lmva_RowHeight - 1 +
3156 (data->icld_ViewY % data->icld_LVMAttribs->lmva_RowHeight);
3158 visible /= data->icld_LVMAttribs->lmva_RowHeight;
3160 return visible;
3163 static void RenderListViewModeHeaderField(Object *obj, struct IconList_DATA *data,
3164 struct Rectangle *rect, LONG index, BOOL sel)
3166 IPTR penFill, penText, penDark, penBright;
3167 struct Rectangle rendRect;
3168 STRPTR text;
3169 struct TextExtent te;
3170 ULONG fit;
3172 if (sel == TRUE)
3174 penFill = _pens(obj)[MPEN_HALFSHADOW];
3175 penBright = _pens(obj)[MPEN_SHADOW];
3176 penDark = _pens(obj)[MPEN_HALFSHINE];
3178 else
3180 penFill = _pens(obj)[MPEN_HALFSHINE];
3181 penBright = _pens(obj)[MPEN_SHINE];
3182 penDark = _pens(obj)[MPEN_HALFSHADOW];
3184 penText = _pens(obj)[MPEN_TEXT];
3186 rendRect.MinX = rect->MinX;
3187 rendRect.MaxX = rect->MaxX;
3188 rendRect.MinY = rect->MinY;
3189 rendRect.MaxY = rect->MaxY;
3191 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3193 rendRect.MinX -= _mleft(obj);
3194 rendRect.MaxX -= _mleft(obj);
3195 rendRect.MinY -= _mtop(obj);
3196 rendRect.MaxY -= _mtop(obj);
3199 #if defined(DEBUG_ILC_FUNCS)
3200 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
3201 #endif
3203 if (((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0) && (index < NUM_COLUMNS))
3205 text = data->icld_LVMAttribs->lmva_ColumnTitle[index];
3207 SetAPen(data->icld_BufferRastPort, penFill); /* Background */
3208 RectFill(data->icld_BufferRastPort, rendRect.MinX + 1, rendRect.MinY + 1,
3209 rendRect.MaxX - 1, rendRect.MaxY - 1);
3211 SetAPen(data->icld_BufferRastPort, penBright); /* Top/Left */
3212 RectFill(data->icld_BufferRastPort, rendRect.MinX, rendRect.MinY, rendRect.MinX, rendRect.MaxY);
3213 RectFill(data->icld_BufferRastPort, rendRect.MinX + 1, rendRect.MinY, rendRect.MaxX - 1, rendRect.MinY);
3215 SetAPen(data->icld_BufferRastPort,penDark); /* Bottom/Right */
3216 RectFill(data->icld_BufferRastPort, rendRect.MaxX, rendRect.MinY, rendRect.MaxX, rendRect.MaxY);
3217 RectFill(data->icld_BufferRastPort, rendRect.MinX + 1, rendRect.MaxY, rendRect.MaxX - 1, rendRect.MaxY);
3219 /* Draw the Sort indicator .. */
3220 if (index == data->icld_LVMAttribs->lmva_SortColumn)
3222 LONG x = rendRect.MaxX - 4 - 6;
3223 LONG y = (rendRect.MinY + rendRect.MaxY + 1) / 2 - 3;
3225 if (x > rendRect.MinX)
3227 SetAPen(data->icld_BufferRastPort, _pens(obj)[sel ? MPEN_SHADOW : MPEN_HALFSHADOW]);
3228 if (data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
3230 RectFill(data->icld_BufferRastPort, x, y, x + 5, y + 1);
3231 RectFill(data->icld_BufferRastPort, x + 1, y + 2, x + 4, y + 3);
3232 RectFill(data->icld_BufferRastPort, x + 2, y + 4, x + 3, y + 5);
3234 else
3236 RectFill(data->icld_BufferRastPort, x, y + 4, x + 5, y + 5);
3237 RectFill(data->icld_BufferRastPort, x + 1, y + 2, x + 4, y + 3);
3238 RectFill(data->icld_BufferRastPort, x + 2, y, x + 3, y + 1);
3243 rendRect.MinX += HEADERENTRY_SPACING_LEFT;
3244 rendRect.MinY += HEADERLINE_SPACING_TOP;
3245 rendRect.MaxX -= HEADERENTRY_SPACING_RIGHT;
3246 rendRect.MaxY -= HEADERLINE_SPACING_BOTTOM;
3248 if (text && text[0])
3251 fit = TextFit(data->icld_BufferRastPort, text, strlen(text), &te, NULL, 1,
3252 rendRect.MaxX - rendRect.MinX + 1,
3253 rendRect.MaxY - rendRect.MinY + 1);
3255 if (!fit) return;
3257 SetABPenDrMd(data->icld_BufferRastPort, penText, 0, JAM1);
3258 Move(data->icld_BufferRastPort, rendRect.MinX, rendRect.MinY + data->icld_BufferRastPort->TxBaseline);
3259 Text(data->icld_BufferRastPort, text, fit);
3264 static void RenderListViewModeHeader(Object *obj, struct IconList_DATA *data)
3266 struct Rectangle linerect;
3267 LONG x, i;
3268 LONG firstvis, lastvis;
3270 #if defined(DEBUG_ILC_FUNCS)
3271 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
3272 #endif
3274 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
3276 linerect.MinX = _mleft(obj) - data->icld_ViewX;
3277 linerect.MaxX = _mright(obj);
3278 linerect.MinY = _mtop(obj);
3279 linerect.MaxY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight - 1;
3281 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
3283 x = linerect.MinX + HEADERLINE_SPACING_LEFT;
3285 firstvis = FirstVisibleColumnNumber(data);
3286 lastvis = LastVisibleColumnNumber(data);
3288 for(i = 0; i < NUM_COLUMNS; i++)
3290 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
3292 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
3294 BOOL outside = FALSE;
3295 struct Rectangle field_rect;
3297 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
3298 field_rect.MinY = linerect.MinY;
3299 field_rect.MaxX = x + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1 + ((i == lastvis) ? HEADERLINE_SPACING_RIGHT : 0);
3300 field_rect.MaxY = linerect.MaxY;
3302 /* data->update_rect1 and data->update_rect2 may
3303 point to rectangles to indicate that only icons
3304 in any of this rectangles need to be drawn */
3305 if (data->update_rect1)
3307 if (!RectAndRect(&field_rect, data->update_rect1))
3308 outside = TRUE;
3311 if (data->update_rect2)
3313 if (data->update_rect1)
3315 if ((outside == TRUE) && RectAndRect(&field_rect, data->update_rect2))
3316 outside = FALSE;
3318 else
3320 if (!RectAndRect(&field_rect, data->update_rect2))
3321 outside = TRUE;
3325 if (outside != TRUE)
3327 RenderListViewModeHeaderField(obj, data, &field_rect, index, FALSE);
3328 x += data->icld_LVMAttribs->lmva_ColumnWidth[index];
3330 #if defined(DEBUG_ILC_ICONRENDERING)
3331 else
3333 D(bug("[IconList] %s: Column '%s' outside of update area .. skipping\n", __PRETTY_FUNCTION__, data->icld_LVMAttribs->lmva_ColumnTitle[i]));
3335 #endif
3338 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_HEADERDRAWTOEND) == LVMAF_HEADERDRAWTOEND)
3340 x += HEADERLINE_SPACING_RIGHT;
3342 if (x < linerect.MaxX)
3344 linerect.MinX = x;
3346 // if (MustRenderRect(data, &linerect))
3347 // {
3348 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_HALFSHINE], 0, JAM1);
3349 RectFill(data->icld_BufferRastPort, linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
3350 // }
3356 ///MUIM_Draw()
3357 /**************************************************************************
3358 MUIM_Draw - draw the IconList
3359 **************************************************************************/
3360 IPTR DrawCount;
3361 IPTR IconList__MUIM_Draw(struct IClass *CLASS, Object *obj, struct MUIP_Draw *message)
3363 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3364 struct IconEntry *entry = NULL;
3366 APTR clip = NULL;
3368 ULONG update_oldwidth = 0,
3369 update_oldheight = 0;
3371 LONG clear_xoffset = 0,
3372 clear_yoffset = 0;
3374 __unused IPTR draw_id = DrawCount++;
3376 #if defined(DEBUG_ILC_FUNCS)
3377 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
3378 #endif
3379 #if defined(DEBUG_ILC_ICONRENDERING)
3380 D(bug("[IconList] %s: id %d\n", __PRETTY_FUNCTION__, draw_id));
3381 #endif
3383 DoSuperMethodA(CLASS, obj, (Msg)message);
3385 if (!(data->icld__Option_IconListFixedBackground))
3387 clear_xoffset = data->icld_ViewX;
3388 clear_yoffset = data->icld_ViewY;
3391 // If window size changes, only update needed areas
3392 if (data->update_oldwidth == 0) data->update_oldwidth = data->icld_ViewWidth;
3393 if (data->update_oldheight == 0) data->update_oldheight = data->icld_ViewHeight;
3394 if ((data->update_oldwidth != data->icld_ViewWidth) || (data->update_oldheight != data->icld_ViewHeight))
3396 if (data->icld_UpdateMode != UPDATE_SCROLL)
3398 data->icld_UpdateMode = UPDATE_RESIZE;
3399 update_oldwidth = data->update_oldwidth;
3400 update_oldheight = data->update_oldheight;
3401 data->update_oldwidth = data->icld_ViewWidth;
3402 data->update_oldheight = data->icld_ViewHeight;
3406 if ((message->flags & MADF_DRAWUPDATE) || (data->icld_UpdateMode == UPDATE_RESIZE))
3408 #if defined(DEBUG_ILC_ICONRENDERING)
3410 if (message->flags & MADF_DRAWUPDATE)
3412 bug("[IconList] %s#%d: MADF_DRAWUPDATE\n", __PRETTY_FUNCTION__, draw_id);
3414 else
3416 bug("[IconList] %s#%d: UPDATE_RESIZE\n", __PRETTY_FUNCTION__, draw_id);
3419 #endif
3420 if ((data->icld_UpdateMode == UPDATE_HEADERENTRY) && ((IPTR)data->update_entry < NUM_COLUMNS)) /* draw the header entry */
3422 struct Rectangle field_rect;
3423 LONG index, i, firstvis, lastvis;
3425 firstvis = FirstVisibleColumnNumber(data);
3426 lastvis = LastVisibleColumnNumber(data);
3428 field_rect.MinX = _mleft(obj) - data->icld_ViewX;
3430 field_rect.MinY = _mtop(obj);
3431 field_rect.MaxY = field_rect.MinY + data->icld_LVMAttribs->lmva_HeaderHeight - 1;
3433 for(i = 0; i < NUM_COLUMNS; i++)
3435 index = data->icld_LVMAttribs->lmva_ColumnPos[i];
3436 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
3438 field_rect.MaxX = field_rect.MinX + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1;
3439 if (index == lastvis)
3440 field_rect.MaxX += HEADERLINE_SPACING_RIGHT;
3442 if ((IPTR)data->update_entry != index)
3444 field_rect.MinX += data->icld_LVMAttribs->lmva_ColumnWidth[index];
3445 if (index == firstvis)
3446 field_rect.MinX += HEADERLINE_SPACING_LEFT;
3448 else
3449 break;
3452 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mright(obj) - _mleft(obj) + 1, data->icld_LVMAttribs->lmva_HeaderHeight);
3454 if (data->icld_LVMAttribs->lmva_LastSelectedColumn == (IPTR)data->update_entry)
3455 RenderListViewModeHeaderField(obj, data, &field_rect, (IPTR)data->update_entry, TRUE);
3456 else
3457 RenderListViewModeHeaderField(obj, data, &field_rect, (IPTR)data->update_entry, FALSE);
3459 data->icld_UpdateMode = 0;
3460 data->update_entry = NULL;
3462 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3464 #if defined(DEBUG_ILC_ICONRENDERING)
3465 D(bug("[IconList] %s#%d: UPDATE_HEADERENTRY Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3466 #endif
3467 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3468 field_rect.MinX - _mleft(obj), field_rect.MinY - _mtop(obj),
3469 data->icld_DisplayRastPort,
3470 field_rect.MinX, field_rect.MinY,
3471 field_rect.MaxX - field_rect.MinX + 1, field_rect.MaxY - field_rect.MinY + 1,
3472 0xC0);
3474 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3476 goto draw_done;
3478 else if ((data->icld_UpdateMode == UPDATE_SINGLEENTRY) && (data->update_entry != NULL)) /* draw only a single entry at update_entry */
3480 struct Rectangle rect;
3482 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3484 LONG count = 0, index = -1;
3486 #if defined(DEBUG_ILC_ICONRENDERING)
3487 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY + ICONLIST_DISP_MODELIST\n", __PRETTY_FUNCTION__, draw_id));
3488 #endif
3489 rect.MinX = _mleft(obj);
3490 rect.MaxX = _mleft(obj) + _mwidth(obj) - 1;
3492 ForeachNode(&data->icld_IconList, entry)
3494 if (entry == data->update_entry)
3496 index = count;
3497 break;
3499 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
3501 count++;
3505 if (index != -1)
3507 rect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight - data->icld_ViewY + (index * data->icld_LVMAttribs->lmva_RowHeight);
3508 rect.MaxY = rect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
3510 if ((rect.MaxY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight))
3511 || (rect.MinY > (_mtop(obj) + _mheight(obj) - 1)))
3512 goto draw_done;
3514 if (rect.MinY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight)) rect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight;
3515 if (rect.MaxY > (_mtop(obj) + _mheight(obj) - 1)) rect.MaxY = _mtop(obj) + _mheight(obj) - 1;
3517 clip = MUI_AddClipping(muiRenderInfo(obj), rect.MinX, rect.MinY, rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1);
3519 DoMethod(obj, MUIM_DrawBackground,
3520 rect.MinX, rect.MinY,
3521 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3522 clear_xoffset, clear_yoffset,
3525 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3526 DoMethod(obj, MUIM_IconList_DrawEntry, data->update_entry, index);
3527 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3528 data->icld_UpdateMode = 0;
3529 data->update_entry = NULL;
3532 else
3534 #if defined(DEBUG_ILC_ICONRENDERING)
3535 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY (entry @ 0x%p)\n", __PRETTY_FUNCTION__, draw_id, data->update_entry));
3536 #endif
3537 IconList_GetIconAreaRectangle(obj, data, data->update_entry, &rect);
3539 rect.MinX += _mleft(obj) + (data->update_entry->ie_IconX - data->icld_ViewX);
3540 rect.MaxX += _mleft(obj) + (data->update_entry->ie_IconX - data->icld_ViewX);
3541 rect.MinY += _mtop(obj) + (data->update_entry->ie_IconY - data->icld_ViewY);
3542 rect.MaxY += _mtop(obj) + (data->update_entry->ie_IconY - data->icld_ViewY);
3544 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
3546 if (data->update_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
3548 rect.MinX += ((data->icld_IconAreaLargestWidth - data->update_entry->ie_AreaWidth)/2);
3549 rect.MaxX += ((data->icld_IconAreaLargestWidth - data->update_entry->ie_AreaWidth)/2);
3552 if (data->update_entry->ie_AreaHeight < data->icld_IconAreaLargestHeight)
3554 rect.MinY += ((data->icld_IconAreaLargestHeight - data->update_entry->ie_AreaHeight)/2);
3555 rect.MaxY += ((data->icld_IconAreaLargestHeight - data->update_entry->ie_AreaHeight)/2);
3559 if (rect.MinX < _mleft(obj)) rect.MinX = _mleft(obj);
3560 if (rect.MaxX > _mright(obj)) rect.MaxX =_mright(obj);
3561 if (rect.MinY < _mtop(obj)) rect.MinY = _mtop(obj);
3562 if (rect.MaxY > _mbottom(obj)) rect.MaxY = _mbottom(obj);
3564 clip = MUI_AddClipping(muiRenderInfo(obj), rect.MinX, rect.MinY, rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1);
3566 #if defined(DEBUG_ILC_ICONRENDERING)
3567 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY: Calling MUIM_DrawBackground (A)\n", __PRETTY_FUNCTION__, draw_id));
3568 #endif
3569 DoMethod(obj, MUIM_DrawBackground,
3570 rect.MinX, rect.MinY,
3571 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3572 clear_xoffset, clear_yoffset,
3575 /* We could have deleted also other icons so they must be redrawn */
3576 #if defined(__AROS__)
3577 ForeachNode(&data->icld_IconList, entry)
3578 #else
3579 Foreach_Node(&data->icld_IconList, entry);
3580 #endif
3582 if ((entry != data->update_entry) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
3584 struct Rectangle rect2;
3585 IconList_GetIconAreaRectangle(obj, data, entry, &rect2);
3587 rect2.MinX += _mleft(obj) - data->icld_ViewX + entry->ie_IconX;
3588 rect2.MaxX += _mleft(obj) - data->icld_ViewX + entry->ie_IconX;
3589 rect2.MinY += _mtop(obj) - data->icld_ViewY + entry->ie_IconY;
3590 rect2.MaxY += _mtop(obj) - data->icld_ViewY + entry->ie_IconY;
3592 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
3594 if (entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
3596 rect2.MinX += ((data->icld_IconAreaLargestWidth - entry->ie_AreaWidth)/2);
3597 rect2.MaxX += ((data->icld_IconAreaLargestWidth - entry->ie_AreaWidth)/2);
3600 if (entry->ie_AreaHeight < data->icld_IconAreaLargestHeight)
3602 rect2.MinY += ((data->icld_IconAreaLargestHeight - entry->ie_AreaHeight)/2);
3603 rect2.MaxY += ((data->icld_IconAreaLargestHeight - entry->ie_AreaHeight)/2);
3607 if (RectAndRect(&rect, &rect2))
3609 // Update entry here
3610 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3611 DoMethod(obj, MUIM_IconList_DrawEntry, entry, ICONENTRY_DRAWMODE_PLAIN);
3612 DoMethod(obj, MUIM_IconList_DrawEntryLabel, entry, ICONENTRY_DRAWMODE_PLAIN);
3613 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3618 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3619 DoMethod(obj, MUIM_IconList_DrawEntry, data->update_entry, ICONENTRY_DRAWMODE_PLAIN);
3620 DoMethod(obj, MUIM_IconList_DrawEntryLabel, data->update_entry, ICONENTRY_DRAWMODE_PLAIN);
3621 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3622 data->icld_UpdateMode = 0;
3623 data->update_entry = NULL;
3625 if (data->update_entry == NULL)
3627 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3629 #if defined(DEBUG_ILC_ICONRENDERING)
3630 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3631 #endif
3632 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3633 rect.MinX - _mleft(obj), rect.MinY - _mtop(obj),
3634 data->icld_DisplayRastPort,
3635 rect.MinX, rect.MinY,
3636 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3637 0xC0);
3639 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3641 goto draw_done;
3643 else if (data->icld_UpdateMode == UPDATE_SCROLL)
3645 struct Region *region = NULL;
3646 struct Rectangle xrect,
3647 yrect;
3648 BOOL scroll_caused_damage = FALSE;
3650 #if defined(DEBUG_ILC_ICONRENDERING)
3651 D(bug("[IconList] %s#%d: UPDATE_SCROLL.\n", __PRETTY_FUNCTION__, draw_id));
3652 #endif
3654 if (!data->icld__Option_IconListFixedBackground)
3656 scroll_caused_damage = (_rp(obj)->Layer->Flags & LAYERREFRESH) ? FALSE : TRUE;
3658 data->icld_UpdateMode = 0;
3660 if ((abs(data->update_scrolldx) >= _mwidth(obj)) ||
3661 (abs(data->update_scrolldy) >= _mheight(obj)))
3663 #if defined(DEBUG_ILC_ICONRENDERING)
3664 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Moved outside current view -> Causing Redraw .. MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3665 #endif
3666 MUI_Redraw(obj, MADF_DRAWOBJECT);
3667 goto draw_done;
3670 if (!(region = NewRegion()))
3672 #if defined(DEBUG_ILC_ICONRENDERING)
3673 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Couldnt Alloc Region -> Causing Redraw ...MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3674 #endif
3675 MUI_Redraw(obj, MADF_DRAWOBJECT);
3676 goto draw_done;
3679 if (data->update_scrolldx > 0)
3681 xrect.MinX = _mright(obj) - data->update_scrolldx;
3682 xrect.MinY = _mtop(obj);
3683 xrect.MaxX = _mright(obj);
3684 xrect.MaxY = _mbottom(obj);
3686 OrRectRegion(region, &xrect);
3688 data->update_rect1 = &xrect;
3690 else if (data->update_scrolldx < 0)
3692 xrect.MinX = _mleft(obj);
3693 xrect.MinY = _mtop(obj);
3694 xrect.MaxX = _mleft(obj) - data->update_scrolldx;
3695 xrect.MaxY = _mbottom(obj);
3697 OrRectRegion(region, &xrect);
3699 data->update_rect1 = &xrect;
3702 if (data->update_scrolldy > 0)
3704 yrect.MinX = _mleft(obj);
3705 yrect.MinY = _mbottom(obj) - data->update_scrolldy;
3706 if (((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3707 && (yrect.MinY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight)))
3709 xrect.MinY = data->icld_LVMAttribs->lmva_HeaderHeight;
3711 yrect.MaxX = _mright(obj);
3712 yrect.MaxY = _mbottom(obj);
3714 OrRectRegion(region, &yrect);
3716 data->update_rect2 = &yrect;
3718 else if (data->update_scrolldy < 0)
3720 yrect.MinX = _mleft(obj);
3721 yrect.MinY = _mtop(obj);
3722 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3724 xrect.MinY += data->icld_LVMAttribs->lmva_HeaderHeight;
3726 yrect.MaxX = _mright(obj);
3727 yrect.MaxY = _mtop(obj) - data->update_scrolldy;
3729 OrRectRegion(region, &yrect);
3731 data->update_rect2 = &yrect;
3734 #if defined(DEBUG_ILC_ICONRENDERING)
3735 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Scrolling Raster..\n", __PRETTY_FUNCTION__, draw_id));
3736 #endif
3737 if (data->icld_DisplayRastPort == data->icld_BufferRastPort)
3739 ScrollRasterBF(data->icld_BufferRastPort,
3740 data->update_scrolldx,
3741 data->update_scrolldy,
3742 _mleft(obj),
3743 _mtop(obj),
3744 _mright(obj),
3745 _mbottom(obj));
3747 else
3749 ScrollRasterBF(data->icld_BufferRastPort,
3750 data->update_scrolldx,
3751 data->update_scrolldy,
3754 _mwidth(obj) - 1,
3755 _mheight(obj) - 1);
3758 scroll_caused_damage = scroll_caused_damage && (_rp(obj)->Layer->Flags & LAYERREFRESH) ? TRUE : FALSE;
3760 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
3763 #if defined(DEBUG_ILC_ICONRENDERING)
3764 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3765 #endif
3766 MUI_Redraw(obj, MADF_DRAWOBJECT);
3768 data->update_rect1 = data->update_rect2 = NULL;
3770 if (!data->icld__Option_IconListFixedBackground)
3772 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
3774 if (scroll_caused_damage)
3776 if (MUI_BeginRefresh(muiRenderInfo(obj), 0))
3778 /* Theoretically it might happen that more damage is caused
3779 after ScrollRaster. By something else, like window movement
3780 in front of our window. Therefore refresh root object of
3781 window, not just this object */
3783 Object *o = NULL;
3785 GET(_win(obj),MUIA_Window_RootObject, &o);
3786 MUI_Redraw(o, MADF_DRAWOBJECT);
3787 #if defined(DEBUG_ILC_ICONRENDERING)
3788 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3789 #endif
3790 MUI_EndRefresh(muiRenderInfo(obj), 0);
3794 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3796 #if defined(DEBUG_ILC_ICONRENDERING)
3797 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3798 #endif
3799 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3800 0, 0,
3801 data->icld_DisplayRastPort,
3802 _mleft(obj), _mtop(obj),
3803 _mwidth(obj), _mheight(obj),
3804 0xC0);
3806 goto draw_done;
3808 else if (data->icld_UpdateMode == UPDATE_RESIZE)
3810 struct Region *region = NULL;
3811 struct Rectangle wrect,
3812 hrect;
3813 ULONG diffw = 0,
3814 diffh = 0;
3816 #if defined(DEBUG_ILC_ICONRENDERING)
3817 D(bug("[IconList] %s#%d: UPDATE_RESIZE.\n", __PRETTY_FUNCTION__, draw_id));
3818 #endif
3820 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
3822 //Free up the buffers Layer, rastport and bitmap so we can replace them ..
3823 if ((GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_WIDTH) != data->icld_ViewWidth)
3824 || (GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_HEIGHT) != data->icld_ViewHeight))
3826 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
3827 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
3828 D(bug("[IconList] %s: Destroying old BackLayer\n", __PRETTY_FUNCTION__));
3829 #endif
3830 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3831 DeleteLayer(0, oldLayer);
3834 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
3836 struct BitMap *bitmap_New;
3837 ULONG tmp_RastDepth;
3838 struct Layer_Info *li = NULL;
3840 tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
3841 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
3842 data->icld_ViewHeight,
3843 tmp_RastDepth,
3844 BMF_CLEAR,
3845 data->icld_DisplayRastPort->BitMap)) != NULL)
3847 if ((data->icld_BufferRastPort = CreateRastPort()) != NULL)
3849 data->icld_BufferRastPort->BitMap = bitmap_New;
3850 if ((li = NewLayerInfo()))
3852 if ((data->icld_BufferRastPort->Layer = CreateUpfrontLayer(li, data->icld_BufferRastPort->BitMap, 0, 0, data->icld_ViewWidth - 1, data->icld_ViewHeight - 1, 0, NULL)))
3855 * Mark it as a buffered rastport.
3858 #if defined(DEBUG_ILC_ATTRIBS) || defined(DEBUG_ILC_ICONRENDERING)
3859 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
3860 #endif
3861 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
3862 data->icld_DrawOffsetX = 0;
3863 data->icld_DrawOffsetY = 0;
3865 else
3866 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3868 else
3869 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3871 else
3872 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3875 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
3877 if (bitmap_New) FreeBitMap(bitmap_New);
3878 if (li) DisposeLayerInfo(li);
3879 data->icld_DrawOffsetX = _mleft(obj);
3880 data->icld_DrawOffsetY = _mtop(obj);
3885 data->icld_UpdateMode = 0;
3887 if (!data->icld__Option_IconListScaledBackground)
3889 if (!(region = NewRegion()))
3891 #if defined(DEBUG_ILC_ICONRENDERING)
3892 D(bug("[IconList] %s#%d: UPDATE_RESIZE: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3893 #endif
3894 MUI_Redraw(obj, MADF_DRAWOBJECT);
3895 goto draw_done;
3898 if ( data->icld_ViewWidth > update_oldwidth )
3899 diffw = data->icld_ViewWidth - update_oldwidth;
3900 if ( data->icld_ViewHeight > update_oldheight )
3901 diffh = data->icld_ViewHeight - update_oldheight;
3903 if (diffw)
3905 wrect.MinX = _mright(obj) - diffw;
3906 wrect.MinY = _mtop(obj);
3907 wrect.MaxX = _mright(obj);
3908 wrect.MaxY = _mbottom(obj);
3909 OrRectRegion(region, &wrect);
3910 data->update_rect1 = &wrect;
3913 if (diffh)
3915 hrect.MinX = _mleft(obj);
3916 hrect.MinY = _mbottom(obj) - diffh;
3917 hrect.MaxX = _mright(obj);
3918 hrect.MaxX = _mright(obj);
3919 hrect.MaxY = _mbottom(obj);
3920 OrRectRegion(region, &hrect);
3921 data->update_rect2 = &hrect;
3923 if (diffh||diffw)
3925 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
3927 else
3929 /* View became smaller both in horizontal and vertical direction.
3930 Nothing to do */
3932 DisposeRegion(region);
3933 goto draw_done;
3937 #if defined(DEBUG_ILC_ICONRENDERING)
3938 D(bug("[IconList] %s#%d: UPDATE_RESIZE: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3939 #endif
3940 MUI_Redraw(obj, MADF_DRAWOBJECT);
3942 if (!data->icld__Option_IconListScaledBackground)
3944 if (diffh||diffw)
3946 data->update_rect1 = data->update_rect2 = NULL;
3947 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
3948 } else DisposeRegion(region);
3951 goto draw_done;
3955 if (message->flags & MADF_DRAWOBJECT)
3957 struct Rectangle viewrect;
3958 int current = 0, first = 0, visible = 0;
3960 #if defined(DEBUG_ILC_ICONRENDERING)
3961 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3962 #endif
3964 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3966 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), data->icld_LVMAttribs->lmva_HeaderHeight);
3967 RenderListViewModeHeader(obj, data);
3969 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3971 #if defined(DEBUG_ILC_ICONRENDERING)
3972 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT Blitting Header to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3973 #endif
3974 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3975 0, 0,
3976 data->icld_DisplayRastPort,
3977 _mleft(obj), _mtop(obj), _mwidth(obj), data->icld_LVMAttribs->lmva_HeaderHeight,
3978 0xC0);
3981 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3983 viewrect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight;
3985 first = FirstVisibleLine(data);
3986 visible = NumVisibleLines(data);
3988 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight, _mwidth(obj), _mheight(obj) - data->icld_LVMAttribs->lmva_HeaderHeight);
3990 else
3992 viewrect.MinY = _mtop(obj);
3993 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj));
3996 viewrect.MaxY = _mtop(obj) + _mheight(obj) - 1;
3997 viewrect.MinX = _mleft(obj);
3998 viewrect.MaxX = _mleft(obj) + _mwidth(obj) - 1;
4000 #if defined(DEBUG_ILC_ICONRENDERING)
4001 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT: Calling MUIM_DrawBackground (B)\n", __PRETTY_FUNCTION__, draw_id));
4002 #endif
4003 DoMethod(
4004 obj, MUIM_DrawBackground, viewrect.MinX, viewrect.MinY, (viewrect.MaxX - viewrect.MinX) + 1, (viewrect.MaxY - viewrect.MinY) + 1,
4005 clear_xoffset, clear_yoffset, 0
4007 #if defined(__AROS__)
4008 ForeachNode(&data->icld_IconList, entry)
4009 #else
4010 Foreach_Node(&data->icld_IconList, entry);
4011 #endif
4013 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
4015 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4017 if ((current >= first) && (current <= (first + visible)))
4019 DoMethod(obj, MUIM_IconList_DrawEntry, entry, current);
4021 current++;
4024 else
4026 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
4027 (entry->ie_DiskObj) &&
4028 (entry->ie_IconX != NO_ICON_POSITION) &&
4029 (entry->ie_IconY != NO_ICON_POSITION))
4031 struct Rectangle iconrect;
4032 IconList_GetIconAreaRectangle(obj, data, entry, &iconrect);
4034 iconrect.MinX += viewrect.MinX - data->icld_ViewX + entry->ie_IconX;
4035 iconrect.MaxX += viewrect.MinX - data->icld_ViewX + entry->ie_IconX;
4036 iconrect.MinY += viewrect.MinY - data->icld_ViewY + entry->ie_IconY;
4037 iconrect.MaxY += viewrect.MinY - data->icld_ViewY + entry->ie_IconY;
4039 if (RectAndRect(&viewrect, &iconrect))
4041 DoMethod(obj, MUIM_IconList_DrawEntry, entry, ICONENTRY_DRAWMODE_PLAIN);
4042 DoMethod(obj, MUIM_IconList_DrawEntryLabel, entry, ICONENTRY_DRAWMODE_PLAIN);
4048 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
4050 #if defined(DEBUG_ILC_ICONRENDERING)
4051 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT: Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
4052 #endif
4053 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
4054 0, 0,
4055 data->icld_DisplayRastPort,
4056 _mleft(obj), _mtop(obj),
4057 _mwidth(obj), _mheight(obj),
4058 0xC0);
4061 MUI_RemoveClipping(muiRenderInfo(obj), clip);
4063 data->icld_UpdateMode = 0;
4065 draw_done:;
4067 #if defined(DEBUG_ILC_ICONRENDERING)
4068 D(bug("[IconList] %s: Draw finished for id %d\n", __PRETTY_FUNCTION__, draw_id));
4069 #endif
4070 return 0;
4074 ///IconList__MUIM_IconList_Update()
4075 /**************************************************************************
4076 MUIM_IconList_Refresh
4077 Implemented by subclasses
4078 **************************************************************************/
4079 IPTR IconList__MUIM_IconList_Update(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Update *message)
4081 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4083 #if defined(DEBUG_ILC_FUNCS)
4084 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4085 #endif
4087 data->icld_FocusIcon = NULL;
4088 SET(obj, MUIA_IconList_Changed, TRUE);
4090 return 1;
4094 ///MUIM_IconList_Clear()
4095 /**************************************************************************
4096 MUIM_IconList_Clear
4097 **************************************************************************/
4098 IPTR IconList__MUIM_IconList_Clear(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Clear *message)
4100 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4101 struct IconEntry *node = NULL;
4103 #if defined(DEBUG_ILC_FUNCS)
4104 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4105 #endif
4107 while ((node = (struct IconEntry*)RemTail((struct List*)&data->icld_IconList)))
4109 DoMethod(obj, MUIM_IconList_DestroyEntry, node);
4112 data->icld_SelectionLastClicked = NULL;
4113 data->icld_FocusIcon = NULL;
4115 data->icld_ViewX = data->icld_ViewY = data->icld_AreaWidth = data->icld_AreaHeight = 0;
4116 data->icld_IconAreaLargestWidth = 0;
4117 data->icld_IconAreaLargestHeight = 0;
4118 data->icld_IconLargestHeight = 0;
4119 data->icld_LabelLargestHeight = 0;
4121 #if defined(DEBUG_ILC_ICONRENDERING)
4122 D(bug("[IconList]: %s: call SetSuperAttrs()\n", __PRETTY_FUNCTION__));
4123 #endif
4124 SetSuperAttrs(CLASS, obj, MUIA_Virtgroup_Left, data->icld_ViewX,
4125 MUIA_Virtgroup_Top, data->icld_ViewY,
4126 TAG_DONE);
4128 #if defined(DEBUG_ILC_ICONRENDERING)
4129 D(bug("[IconList]: %s: call SetAttrs()\n", __PRETTY_FUNCTION__));
4130 #endif
4131 SetAttrs(obj, MUIA_Virtgroup_Left, data->icld_ViewX,
4132 MUIA_Virtgroup_Top, data->icld_ViewY,
4133 TAG_DONE);
4135 #if defined(DEBUG_ILC_ICONRENDERING)
4136 D(bug("[IconList]: %s: Set MUIA_IconList_Width and MUIA_IconList_Height\n", __PRETTY_FUNCTION__));
4137 #endif
4138 SetAttrs(obj, MUIA_IconList_Width, data->icld_AreaWidth,
4139 MUIA_IconList_Height, data->icld_AreaHeight,
4140 TAG_DONE);
4142 D(bug("[IconList]: %s: call MUI_Redraw()\n", __PRETTY_FUNCTION__));
4143 MUI_Redraw(obj,MADF_DRAWOBJECT);
4144 return 1;
4148 ///IconList__MUIM_IconList_DestroyEntry()
4149 IPTR IconList__MUIM_IconList_DestroyEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DestroyEntry *message)
4151 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4153 #if defined(DEBUG_ILC_FUNCS)
4154 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4155 #endif
4157 if (message->entry)
4159 if (message->entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
4161 if (data->icld_SelectionLastClicked == message->entry)
4163 struct IconList_Entry *nextentry = &message->entry->ie_IconListEntry;
4165 /* get selected entries from SOURCE iconlist */
4166 DoMethod(obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&nextentry);
4167 if ((nextentry) && ((IPTR)nextentry != MUIV_IconList_NextIcon_End))
4168 data->icld_SelectionLastClicked = (struct IconEntry *)((IPTR)nextentry - ((IPTR)&message->entry->ie_IconListEntry - (IPTR)message->entry));
4169 else
4170 data->icld_SelectionLastClicked = NULL;
4172 if (data->icld_FocusIcon == message->entry)
4173 data->icld_FocusIcon = data->icld_SelectionLastClicked;
4175 Remove(&message->entry->ie_SelectionNode);
4178 if (message->entry->ie_TxtBuf_DisplayedLabel)
4179 FreeVecPooled(data->icld_Pool, message->entry->ie_TxtBuf_DisplayedLabel);
4181 if (message->entry->ie_TxtBuf_PROT)
4182 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_PROT, 8);
4184 if (message->entry->ie_TxtBuf_SIZE)
4185 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_SIZE, 30);
4187 if (message->entry->ie_TxtBuf_TIME)
4188 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_TIME, LEN_DATSTRING);
4190 if (message->entry->ie_TxtBuf_DATE)
4191 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_DATE, LEN_DATSTRING);
4193 if (message->entry->ie_DiskObj)
4194 FreeDiskObject(message->entry->ie_DiskObj);
4196 if (message->entry->ie_FileInfoBlock)
4197 FreeMem(message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4199 if (message->entry->ie_IconListEntry.label)
4200 FreePooled(data->icld_Pool, message->entry->ie_IconListEntry.label, strlen(message->entry->ie_IconListEntry.label)+1);
4202 if (message->entry->ie_IconNode.ln_Name)
4203 FreePooled(data->icld_Pool, message->entry->ie_IconNode.ln_Name, strlen(message->entry->ie_IconNode.ln_Name)+1);
4205 FreePooled(data->icld_Pool, message->entry, sizeof(struct IconEntry));
4207 return (IPTR)TRUE;
4211 ///IconList__MUIM_IconList_PropagateEntryPos()
4212 IPTR IconList__MUIM_IconList_PropagateEntryPos(struct IClass *CLASS, Object *obj,
4213 struct MUIP_IconList_PropagateEntryPos *message)
4215 message->entry->ie_ProvidedIconX = message->entry->ie_IconX;
4216 message->entry->ie_ProvidedIconY = message->entry->ie_IconY;
4218 return (IPTR)TRUE;
4222 ///IconList__MUIM_IconList_CreateEntry()
4223 /**************************************************************************
4224 MUIM_IconList_CreateEntry.
4225 Returns 0 on failure otherwise it returns the icons entry ..
4226 **************************************************************************/
4227 IPTR IconList__MUIM_IconList_CreateEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_CreateEntry *message)
4229 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4230 struct IconEntry *entry = NULL;
4231 struct DateTime dt;
4232 struct DateStamp now;
4233 UBYTE *sp = NULL;
4235 struct DiskObject *dob = NULL;
4236 struct Rectangle rect;
4238 IPTR geticon_error = 0;
4240 #if defined(DEBUG_ILC_FUNCS)
4241 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4242 #endif
4244 /*disk object (icon)*/
4245 if (message->entry_dob == NULL)
4247 IPTR iconlistScreen = (IPTR)_screen(obj);
4248 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
4250 dob = GetIconTags
4252 message->filename,
4253 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
4254 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
4255 ICONGETA_FailIfUnavailable, FALSE,
4256 ICONGETA_GenerateImageMasks, TRUE,
4257 ICONA_ErrorCode, &geticon_error,
4258 TAG_DONE
4261 if (dob == NULL)
4263 D(bug("[IconList] %s: Fatal: Couldnt get DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
4265 return (IPTR)NULL;
4268 else
4270 dob = message->entry_dob;
4273 D(bug("[IconList] %s: DiskObject @ 0x%p\n", __PRETTY_FUNCTION__, dob));
4275 if ((entry = AllocPooled(data->icld_Pool, sizeof(struct IconEntry))) == NULL)
4277 D(bug("[IconList] %s: Failed to Allocate Entry Storage!\n", __PRETTY_FUNCTION__));
4278 FreeDiskObject(dob);
4279 return (IPTR)NULL;
4281 memset(entry, 0, sizeof(struct IconEntry));
4282 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4283 entry->ie_IconListEntry.ile_IconEntry = entry;
4285 /* Allocate Text Buffers */
4287 if ((entry->ie_TxtBuf_DATE = AllocPooled(data->icld_Pool, LEN_DATSTRING)) == NULL)
4289 D(bug("[IconList] %s: Failed to Allocate Entry DATE Storage!\n", __PRETTY_FUNCTION__));
4290 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4291 return (IPTR)NULL;
4293 memset(entry->ie_TxtBuf_DATE, 0, LEN_DATSTRING);
4295 if ((entry->ie_TxtBuf_TIME = AllocPooled(data->icld_Pool, LEN_DATSTRING)) == NULL)
4297 D(bug("[IconList] %s: Failed to Allocate Entry TIME string Storage!\n", __PRETTY_FUNCTION__));
4298 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4299 return (IPTR)NULL;
4301 memset(entry->ie_TxtBuf_TIME, 0, LEN_DATSTRING);
4303 if ((entry->ie_TxtBuf_SIZE = AllocPooled(data->icld_Pool, 30)) == NULL)
4305 D(bug("[IconList] %s: Failed to Allocate Entry SIZE string Storage!\n", __PRETTY_FUNCTION__));
4306 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4307 return (IPTR)NULL;
4309 memset(entry->ie_TxtBuf_SIZE, 0, 30);
4311 if ((entry->ie_TxtBuf_PROT = AllocPooled(data->icld_Pool, 8)) == NULL)
4313 D(bug("[IconList] %s: Failed to Allocate Entry PROT Flag string Storage!\n", __PRETTY_FUNCTION__));
4314 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4315 return (IPTR)NULL;
4317 memset(entry->ie_TxtBuf_PROT, 0, 8);
4319 /*alloc filename*/
4320 if ((entry->ie_IconNode.ln_Name = AllocPooled(data->icld_Pool, strlen(message->filename) + 1)) == NULL)
4322 D(bug("[IconList] %s: Failed to Allocate Entry filename string Storage!\n", __PRETTY_FUNCTION__));
4323 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4324 return (IPTR)NULL;
4327 /*alloc entry label*/
4328 if ((entry->ie_IconListEntry.label = AllocPooled(data->icld_Pool, strlen(message->label) + 1)) == NULL)
4330 D(bug("[IconList] %s: Failed to Allocate Entry label string Storage!\n", __PRETTY_FUNCTION__));
4331 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4332 return (IPTR)NULL;
4335 /*file info block*/
4336 if(message->fib != NULL)
4338 if ((entry->ie_FileInfoBlock = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)) != NULL)
4340 CopyMem(message->fib, entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4342 if (entry->ie_FileInfoBlock->fib_DirEntryType > 0)
4344 strcpy(entry->ie_TxtBuf_SIZE, "Drawer");
4346 else
4348 FmtSizeToString(entry->ie_TxtBuf_SIZE, entry->ie_FileInfoBlock->fib_Size);
4351 dt.dat_Stamp = entry->ie_FileInfoBlock->fib_Date;
4352 dt.dat_Format = FORMAT_DEF;
4353 dt.dat_Flags = 0;
4354 dt.dat_StrDay = NULL;
4355 dt.dat_StrDate = entry->ie_TxtBuf_DATE;
4356 dt.dat_StrTime = entry->ie_TxtBuf_TIME;
4358 DateToStr(&dt);
4359 DateStamp(&now);
4361 /*if modified today show time, otherwise just show date*/
4362 if (now.ds_Days == entry->ie_FileInfoBlock->fib_Date.ds_Days)
4363 entry->ie_Flags |= ICONENTRY_FLAG_TODAY;
4364 else
4365 entry->ie_Flags &= ~ICONENTRY_FLAG_TODAY;
4367 sp = entry->ie_TxtBuf_PROT;
4368 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_SCRIPT) ? 's' : '-';
4369 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_PURE) ? 'p' : '-';
4370 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
4371 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_READ) ? '-' : 'r';
4372 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_WRITE) ? '-' : 'w';
4373 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
4374 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_DELETE) ? '-' : 'd';
4375 *sp++ = '\0';
4377 entry->ie_IconListEntry.type = entry->ie_FileInfoBlock->fib_DirEntryType;
4380 else
4382 entry->ie_IconListEntry.type = ST_USERDIR;
4385 /* Override type if specified during createntry */
4386 if (message->type != 0)
4388 entry->ie_IconListEntry.type = message->type;
4389 D(bug("[IconList] %s: Overide Entry Type. New Type = %x\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.type));
4391 else
4393 D(bug("[IconList] %s: Entry Type = %x\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.type));
4396 strcpy(entry->ie_IconNode.ln_Name, message->filename);
4397 strcpy(entry->ie_IconListEntry.label, message->label);
4399 entry->ie_IconListEntry.udata = NULL;
4401 entry->ie_IconX = dob->do_CurrentX;
4402 entry->ie_IconY = dob->do_CurrentY;
4404 DoMethod(obj, MUIM_IconList_PropagateEntryPos, entry);
4406 if (IconList__LabelFunc_CreateLabel(obj, data, entry) != (IPTR)NULL)
4408 entry->ie_DiskObj = dob;
4410 /* Use a geticonrectangle routine that gets textwidth! */
4411 IconList_GetIconAreaRectangle(obj, data, entry, &rect);
4413 return (IPTR)entry;
4416 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
4417 return (IPTR)NULL;
4421 ///IconList__MUIM_IconList_UpdateEntry()
4422 /**************************************************************************
4423 MUIM_IconList_UpdateEntry.
4424 Returns 0 on failure otherwise it returns the icons entry ..
4425 **************************************************************************/
4426 IPTR IconList__MUIM_IconList_UpdateEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_UpdateEntry *message)
4428 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4429 // struct DateTime dt;
4430 // struct DateStamp now;
4431 // UBYTE *sp = NULL;
4433 // struct DiskObject *dob = NULL;
4434 struct Rectangle rect;
4436 // IPTR geticon_error = 0;
4438 #if defined(DEBUG_ILC_FUNCS)
4439 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4440 #endif
4442 /* Update disk object (icon)*/
4443 /* if (message->entry_dob == NULL)
4445 IPTR iconlistScreen = _screen(obj);
4446 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
4448 dob = GetIconTags
4450 message->filename,
4451 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
4452 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
4453 ICONGETA_FailIfUnavailable, FALSE,
4454 ICONGETA_GenerateImageMasks, TRUE,
4455 ICONA_ErrorCode, &geticon_error,
4456 TAG_DONE
4459 if (dob == NULL)
4461 D(bug("[IconList] %s: Fatal: Couldnt get DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
4463 return (IPTR)NULL;
4466 else
4468 dob = message->entry_dob;
4471 D(bug("[IconList] %s: DiskObject @ 0x%p\n", __PRETTY_FUNCTION__, dob));
4474 /* Update filename */
4475 if (strcmp(message->entry->ie_IconNode.ln_Name, message->filename) != 0)
4477 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4478 FreePooled(data->icld_Pool, message->entry->ie_IconNode.ln_Name, strlen(message->entry->ie_IconNode.ln_Name) + 1);
4479 if ((message->entry->ie_IconNode.ln_Name = AllocPooled(data->icld_Pool, strlen(message->filename) + 1)) == NULL)
4481 D(bug("[IconList] %s: Failed to Allocate Entry filename string Storage!\n", __PRETTY_FUNCTION__));
4482 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4483 return (IPTR)NULL;
4485 strcpy(message->entry->ie_IconNode.ln_Name, message->filename);
4488 /* Update entry label */
4489 if (strcmp(message->entry->ie_IconListEntry.label, message->label) != 0)
4491 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4492 FreePooled(data->icld_Pool, message->entry->ie_IconListEntry.label, strlen(message->entry->ie_IconListEntry.label) + 1);
4493 if ((message->entry->ie_IconListEntry.label = AllocPooled(data->icld_Pool, strlen(message->label) + 1)) == NULL)
4495 D(bug("[IconList] %s: Failed to Allocate Entry label string Storage!\n", __PRETTY_FUNCTION__));
4496 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4497 return (IPTR)NULL;
4499 strcpy(message->entry->ie_IconListEntry.label, message->label);
4500 if (IconList__LabelFunc_CreateLabel(obj, data, message->entry) == (IPTR)NULL)
4502 D(bug("[IconList] %s: Failed to create label\n", __PRETTY_FUNCTION__));
4503 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4504 return (IPTR)NULL;
4508 /* Update file info block */
4509 if(message->fib != NULL)
4511 if (!(message->entry->ie_FileInfoBlock))
4513 if ((message->entry->ie_FileInfoBlock = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)) != NULL)
4515 CopyMem(message->fib, message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4519 /* if (entry->ie_FileInfoBlock->fib_DirEntryType > 0)
4521 strcpy(entry->ie_TxtBuf_SIZE, "Drawer");
4523 else
4525 FmtSizeToString(entry->ie_TxtBuf_SIZE, entry->ie_FileInfoBlock->fib_Size);
4528 dt.dat_Stamp = entry->ie_FileInfoBlock->fib_Date;
4529 dt.dat_Format = FORMAT_DEF;
4530 dt.dat_Flags = 0;
4531 dt.dat_StrDay = NULL;
4532 dt.dat_StrDate = entry->ie_TxtBuf_DATE;
4533 dt.dat_StrTime = entry->ie_TxtBuf_TIME;
4535 DateToStr(&dt);
4536 DateStamp(&now);
4538 //if modified today show time, otherwise just show date
4539 if (now.ds_Days == entry->ie_FileInfoBlock->fib_Date.ds_Days)
4540 entry->ie_Flags |= ICONENTRY_FLAG_TODAY;
4541 else
4542 entry->ie_Flags &= ~ICONENTRY_FLAG_TODAY;
4544 sp = entry->ie_TxtBuf_PROT;
4545 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_SCRIPT) ? 's' : '-';
4546 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_PURE) ? 'p' : '-';
4547 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
4548 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_READ) ? '-' : 'r';
4549 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_WRITE) ? '-' : 'w';
4550 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
4551 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_DELETE) ? '-' : 'd';
4552 *sp++ = '\0';
4554 entry->ie_IconListEntry.type = entry->ie_FileInfoBlock->fib_DirEntryType;
4557 else
4559 if (message->entry->ie_FileInfoBlock)
4560 FreeMem(message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4562 if (message->entry->ie_IconListEntry.type != ST_USERDIR)
4564 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4565 message->entry->ie_IconListEntry.type = ST_USERDIR;
4569 /* Override type if specified */
4570 if ((message->type != 0) && (message->entry->ie_IconListEntry.type != message->type))
4572 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4573 message->entry->ie_IconListEntry.type = message->type;
4574 D(bug("[IconList] %s: Overide Entry Type. New Type = %x\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.type));
4576 else
4578 D(bug("[IconList] %s: Entry Type = %x\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.type));
4581 IconList_GetIconAreaRectangle(obj, data, message->entry, &rect);
4583 return (IPTR)message->entry;
4587 ///DoWheelMove()
4588 static void DoWheelMove(struct IClass *CLASS, Object *obj, LONG wheelx, LONG wheely, UWORD qual)
4590 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4592 LONG newleft = data->icld_ViewX,
4593 newtop = data->icld_ViewY;
4595 /* Use horizontal scrolling if any of the following cases are true ...
4597 # vertical wheel is used but there's nothing to scroll
4598 (everything is visible already) ..
4600 # vertical wheel is used and one of the ALT keys is down. */
4602 if ((wheely && !wheelx) &&
4603 ((data->icld_AreaHeight <= _mheight(obj)) || (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))))
4605 wheelx = wheely; wheely = 0;
4608 if (qual & (IEQUALIFIER_CONTROL))
4610 if (wheelx < 0) newleft = 0;
4611 if (wheelx > 0) newleft = data->icld_AreaWidth;
4612 if (wheely < 0) newtop = 0;
4613 if (wheely > 0) newtop = data->icld_AreaHeight;
4615 else if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
4617 newleft += (wheelx * _mwidth(obj));
4618 newtop += (wheely * _mheight(obj));
4620 else
4622 newleft += wheelx * 30;
4623 newtop += wheely * 30;
4626 if (newleft + _mwidth(obj) > data->icld_AreaWidth)
4627 newleft = data->icld_AreaWidth - _mwidth(obj);
4628 if (newleft < 0)
4629 newleft = 0;
4631 if (newtop + _mheight(obj) > data->icld_AreaHeight)
4632 newtop = data->icld_AreaHeight - _mheight(obj);
4633 if (newtop < 0)
4634 newtop = 0;
4636 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
4638 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
4639 MUIA_Virtgroup_Top, newtop,
4640 TAG_DONE);
4645 /* Notes:
4647 * LEFTDOWN
4648 * a) if clicked object is selected, nothing
4649 * b) if clicked object is not selected, unselect all, select object
4650 * c) if no clicked object, start lasso
4651 * LEFTUP
4652 * a) if in lasso, finish lasso
4653 * LEFTDOWN + SHIFT
4654 * a) if object is selected, unselect it (= remove from multiselection)
4655 * b) if object is not selected, select it (= add to multiselection)
4658 * Expected behaviour:
4659 * a) you can only "remove" multiselection by clicking on not selected object or on space where there is no icon
4663 static void IconList_HandleNewIconSelection(struct IClass *CLASS, Object *obj, struct MUIP_HandleEvent *message,
4664 struct IconEntry *new_selected, BOOL *doubleclicked)
4666 struct IconEntry *node = NULL;
4667 BOOL update_entry = FALSE;
4668 LONG mx = message->imsg->MouseX - _mleft(obj);
4669 LONG my = message->imsg->MouseY - _mtop(obj);
4670 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4671 BOOL nounselection = (new_selected != NULL &&
4672 (new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED)); /* see notes above */
4675 /* Check if this is a double click on icon or empty space */
4676 if ((DoubleClick(data->last_secs, data->last_mics, message->imsg->Seconds, message->imsg->Micros)) && (data->icld_SelectionLastClicked == new_selected))
4678 #if defined(DEBUG_ILC_EVENTS)
4679 D(bug("[IconList] %s: Entry double-clicked\n", __PRETTY_FUNCTION__));
4680 #endif
4681 *doubleclicked = TRUE;
4684 /* Deselection lopp */
4685 #if defined(__AROS__)
4686 ForeachNode(&data->icld_IconList, node)
4687 #else
4688 Foreach_Node(&data->icld_IconList, node);
4689 #endif
4691 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4693 update_entry = FALSE;
4695 /* If node that is being checked is selected and it is not the clicked node
4696 * and no shift pressed and
4697 * clicked node is not part of selection (see notes above) or this is a double click */
4698 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
4700 if ((new_selected != node) &&
4701 (!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))) &&
4702 (!nounselection || *doubleclicked))
4704 Remove(&node->ie_SelectionNode);
4705 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
4706 update_entry = TRUE;
4710 /* Remove focus */
4711 if ((node->ie_Flags & ICONENTRY_FLAG_FOCUS) && (new_selected != node))
4713 node->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
4714 update_entry = TRUE;
4717 /* Redraw list */
4718 if (update_entry)
4720 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4721 data->update_entry = node;
4722 MUI_Redraw(obj, MADF_DRAWUPDATE);
4723 #if defined(DEBUG_ILC_EVENTS)
4724 D(bug("[IconList] %s: Rendered entry '%s'\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
4725 #endif
4730 if (new_selected != NULL)
4732 /* Found clicked entry... */
4733 data->icld_LassoActive = FALSE;
4734 update_entry = FALSE;
4736 if (!(new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED))
4738 /* Add new entry to selection */
4739 AddTail(&data->icld_SelectionList, &new_selected->ie_SelectionNode);
4740 new_selected->ie_Flags |= ICONENTRY_FLAG_SELECTED;
4741 update_entry = TRUE;
4743 else if ((*doubleclicked == FALSE) && (message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
4745 /* Unselect previously selected entry */
4746 Remove(&new_selected->ie_SelectionNode);
4747 new_selected->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
4748 update_entry = TRUE;
4751 /* Set focus */
4752 if (!(new_selected->ie_Flags & ICONENTRY_FLAG_FOCUS))
4754 new_selected->ie_Flags |= ICONENTRY_FLAG_FOCUS;
4755 data->icld_FocusIcon = new_selected;
4756 update_entry = TRUE;
4759 /* Redraw list */
4760 if (update_entry)
4762 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4763 data->update_entry = new_selected;
4764 MUI_Redraw(obj, MADF_DRAWUPDATE);
4765 #if defined(DEBUG_ILC_EVENTS)
4766 D(bug("[IconList] %s: Rendered 'new_selected' entry '%s'\n", __PRETTY_FUNCTION__, new_selected->ie_IconListEntry.label));
4767 #endif
4770 else
4772 struct Window * thisWindow = NULL;
4773 #if defined(DEBUG_ILC_EVENTS) || defined(DEBUG_ILC_LASSO)
4774 D(bug("[IconList] %s: Starting Lasso\n", __PRETTY_FUNCTION__));
4775 #endif
4776 /* No entry clicked on ... Start Lasso-selection */
4777 data->icld_LassoActive = TRUE;
4778 if (!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
4780 data->icld_SelectionLastClicked = NULL;
4781 data->icld_FocusIcon = NULL;
4783 data->icld_LassoRectangle.MinX = mx - data->view_rect.MinX + data->icld_ViewX;
4784 data->icld_LassoRectangle.MinY = my - data->view_rect.MinY + data->icld_ViewY;
4785 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
4786 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
4788 /* Draw initial Lasso frame */
4789 IconList_InvertLassoOutlines(obj, data, &data->icld_LassoRectangle);
4791 /* Start handling INTUITICKS */
4792 GET(obj, MUIA_Window, &thisWindow);
4793 if (thisWindow)
4795 ModifyIDCMP(thisWindow, (thisWindow->IDCMPFlags|IDCMP_INTUITICKS));
4796 if (!(data->ehn.ehn_Events & IDCMP_INTUITICKS))
4798 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
4799 data->ehn.ehn_Events |= IDCMP_INTUITICKS;
4800 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
4806 ///MUIM_HandleEvent()
4807 /**************************************************************************
4808 MUIM_HandleEvent
4809 **************************************************************************/
4810 IPTR IconList__MUIM_HandleEvent(struct IClass *CLASS, Object *obj, struct MUIP_HandleEvent *message)
4812 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4814 #if defined(DEBUG_ILC_FUNCS)
4815 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4816 #endif
4818 if (message->imsg)
4820 LONG mx = message->imsg->MouseX - _mleft(obj);
4821 LONG my = message->imsg->MouseY - _mtop(obj);
4823 LONG wheelx = 0;
4824 LONG wheely = 0;
4826 switch (message->imsg->Class)
4828 case IDCMP_NEWSIZE:
4829 bug("[IconList] %s: IDCMP_NEWSIZE\n", __PRETTY_FUNCTION__);
4830 break;
4832 case IDCMP_RAWKEY:
4834 #if defined(DEBUG_ILC_EVENTS)
4835 D(bug("[IconList] %s: IDCMP_RAWKEY\n", __PRETTY_FUNCTION__));
4836 #endif
4837 BOOL rawkey_handled = FALSE;
4839 switch(message->imsg->Code)
4841 case RAWKEY_NM_WHEEL_UP:
4842 wheely = -1;
4843 rawkey_handled = TRUE;
4844 break;
4846 case RAWKEY_NM_WHEEL_DOWN:
4847 wheely = 1;
4848 rawkey_handled = TRUE;
4849 break;
4851 case RAWKEY_NM_WHEEL_LEFT:
4852 wheelx = -1;
4853 rawkey_handled = TRUE;
4854 break;
4856 case RAWKEY_NM_WHEEL_RIGHT:
4857 wheelx = 1;
4858 rawkey_handled = TRUE;
4859 break;
4862 if (rawkey_handled)
4864 #if defined(DEBUG_ILC_KEYEVENTS)
4865 D(bug("[IconList] %s: Processing mouse wheel event\n", __PRETTY_FUNCTION__));
4866 #endif
4867 if (_isinobject(message->imsg->MouseX, message->imsg->MouseY) &&
4868 (wheelx || wheely))
4870 DoWheelMove(CLASS, obj, wheelx, wheely, message->imsg->Qualifier);
4873 else if (!(message->imsg->Code & IECODE_UP_PREFIX))
4875 LONG new_ViewY = data->icld_ViewY;
4876 struct IconEntry *start_entry = NULL, *active_entry = NULL, *entry_next = NULL;
4877 IPTR start_X = 0, start_Y = 0, active_X = 0, active_Y = 0, next_X = 0, next_Y = 0;
4878 IPTR x_diff = 0;
4880 #if defined(DEBUG_ILC_KEYEVENTS)
4881 D(bug("[IconList] %s: Processing key up event\n", __PRETTY_FUNCTION__));
4882 #endif
4884 switch(message->imsg->Code)
4886 case RAWKEY_RETURN:
4887 rawkey_handled = TRUE;
4889 #if defined(DEBUG_ILC_KEYEVENTS)
4890 D(bug("[IconList] %s: RAWKEY_RETURN\n", __PRETTY_FUNCTION__));
4891 #endif
4893 if (data->icld_FocusIcon) active_entry = data->icld_FocusIcon;
4894 else if (data->icld_SelectionLastClicked) active_entry = data->icld_SelectionLastClicked;
4896 if (active_entry)
4898 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
4900 active_entry->ie_Flags |= ICONENTRY_FLAG_SELECTED;
4901 AddTail(&data->icld_SelectionList, &active_entry->ie_SelectionNode);
4902 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4903 data->update_entry = active_entry;
4904 MUI_Redraw(obj, MADF_DRAWUPDATE);
4906 data->icld_SelectionLastClicked = active_entry;
4907 data->icld_FocusIcon = active_entry;
4909 SET(obj, MUIA_IconList_DoubleClick, TRUE);
4911 break;
4913 case RAWKEY_SPACE:
4914 rawkey_handled = TRUE;
4916 #if defined(DEBUG_ILC_KEYEVENTS)
4917 D(bug("[IconList] %s: RAWKEY_SPACE\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 (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)||(data->icld_SelectionLastClicked != active_entry)))
4925 #if defined(DEBUG_ILC_KEYEVENTS)
4926 D(bug("[IconList] %s: SPACE: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
4927 #endif
4928 DoMethod(obj, MUIM_IconList_UnselectAll);
4931 if (active_entry)
4933 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
4935 AddTail(&data->icld_SelectionList, &active_entry->ie_SelectionNode);
4936 active_entry->ie_Flags |= ICONENTRY_FLAG_SELECTED;
4937 data->icld_SelectionLastClicked = active_entry;
4939 else
4941 Remove(&active_entry->ie_SelectionNode);
4942 active_entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
4945 data->icld_FocusIcon = active_entry;
4947 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4948 data->update_entry = active_entry;
4949 MUI_Redraw(obj, MADF_DRAWUPDATE);
4951 break;
4953 case RAWKEY_PAGEUP:
4954 rawkey_handled = TRUE;
4956 #if defined(DEBUG_ILC_KEYEVENTS)
4957 D(bug("[IconList] %s: RAWKEY_PAGEUP\n", __PRETTY_FUNCTION__));
4958 #endif
4960 if (data->icld_AreaHeight > data->icld_ViewHeight)
4962 new_ViewY -= data->icld_ViewHeight;
4963 if (new_ViewY< 0)
4964 new_ViewY = 0;
4967 if (new_ViewY != data->icld_ViewY)
4969 SET(obj, MUIA_Virtgroup_Top, new_ViewY);
4971 break;
4973 case RAWKEY_PAGEDOWN:
4974 rawkey_handled = TRUE;
4976 #if defined(DEBUG_ILC_KEYEVENTS)
4977 D(bug("[IconList] %s: RAWKEY_PAGEDOWN\n", __PRETTY_FUNCTION__));
4978 #endif
4980 if (data->icld_AreaHeight > data->icld_ViewHeight)
4982 new_ViewY += data->icld_ViewHeight;
4983 if (new_ViewY > (data->icld_AreaHeight - data->icld_ViewHeight))
4984 new_ViewY = data->icld_AreaHeight - data->icld_ViewHeight;
4987 if (new_ViewY != data->icld_ViewY)
4989 SET(obj, MUIA_Virtgroup_Top, new_ViewY);
4991 break;
4993 case RAWKEY_UP:
4994 rawkey_handled = TRUE;
4996 #if defined(DEBUG_ILC_KEYEVENTS)
4997 D(bug("[IconList] %s: RAWKEY_UP\n", __PRETTY_FUNCTION__));
4998 #endif
5000 if (data->icld_FocusIcon)
5002 start_entry = data->icld_FocusIcon;
5003 #if defined(DEBUG_ILC_KEYEVENTS)
5004 D(bug("[IconList] %s: UP: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5005 #endif
5007 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5008 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5009 data->update_entry = start_entry;
5010 MUI_Redraw(obj, MADF_DRAWUPDATE);
5012 start_X = start_entry->ie_IconX;
5013 start_Y = start_entry->ie_IconY;
5014 #if defined(DEBUG_ILC_KEYEVENTS)
5015 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));
5016 #endif
5017 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5019 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5021 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5022 #if defined(DEBUG_ILC_KEYEVENTS)
5023 D(bug("[IconList] %s: UP: adjusted start_X for grid = %d\n", __PRETTY_FUNCTION__, start_X));
5024 #endif
5028 if ((active_entry = Node_PreviousVisible(start_entry)) && !(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5030 //Check if we are at the edge of the entry area ..
5031 #if defined(DEBUG_ILC_KEYEVENTS)
5032 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));
5033 #endif
5034 active_Y = active_entry->ie_IconY;
5036 if (active_Y == start_Y)
5039 #if defined(DEBUG_ILC_KEYEVENTS)
5040 D(bug("[IconList] %s: UP: active_entry is on our row (not at the edge)\n", __PRETTY_FUNCTION__));
5041 #endif
5042 entry_next = active_entry;
5043 next_X = entry_next->ie_IconX;
5044 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5046 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5047 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5051 #if defined(DEBUG_ILC_KEYEVENTS)
5052 D(bug("[IconList] %s: UP: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5053 #endif
5056 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5058 #if defined(DEBUG_ILC_KEYEVENTS)
5059 D(bug("[IconList] %s: UP: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5060 #endif
5061 DoMethod(obj, MUIM_IconList_UnselectAll);
5064 #if defined(DEBUG_ILC_KEYEVENTS)
5065 D(bug("[IconList] %s: UP: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5066 #endif
5067 if (!(active_entry))
5069 // If nothing is selected we will use the last visible entry ..
5070 active_entry = Node_LastVisible(&data->icld_IconList);
5071 start_X = active_entry->ie_IconX;
5072 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5074 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5075 start_X = start_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5077 start_Y = active_entry->ie_IconY;
5080 while (active_entry != NULL)
5082 #if defined(DEBUG_ILC_KEYEVENTS)
5083 D(bug("[IconList] %s: UP: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5084 #endif
5085 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
5087 // Return the first visible since the list flow direction matches
5088 // our cursor direction
5089 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5090 break;
5092 else
5094 active_X = active_entry->ie_IconX;
5096 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5098 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5099 x_diff = ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5101 active_Y = active_entry->ie_IconY;
5103 if (start_entry)
5105 if (entry_next)
5107 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5108 (active_Y < start_Y) &&
5109 (((active_X - x_diff) >= start_X ) &&
5110 ((active_X - x_diff) <= (start_X + start_entry->ie_AreaWidth + (x_diff*2)))))
5112 #if defined(DEBUG_ILC_KEYEVENTS)
5113 D(bug("[IconList] %s: UP: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5114 #endif
5115 break;
5117 else if (active_entry == (struct IconEntry *)GetHead(&data->icld_IconList))
5119 #if defined(DEBUG_ILC_KEYEVENTS)
5120 D(bug("[IconList] %s: UP: (A) reached list start .. restarting from the end ..\n", __PRETTY_FUNCTION__));
5121 #endif
5122 start_X = next_X;
5124 if ((entry_next = Node_PreviousVisible(entry_next)))
5126 if (entry_next->ie_IconX > start_X)
5127 entry_next = NULL;
5128 else
5130 next_X = entry_next->ie_IconX;
5131 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5133 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5134 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5138 start_Y = 0;
5139 #if defined(DEBUG_ILC_KEYEVENTS)
5140 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));
5141 #endif
5142 active_entry = Node_LastVisible(&data->icld_IconList);
5145 else
5147 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5148 (active_Y < start_Y) &&
5149 ((active_X + x_diff) < (start_X + start_entry->ie_AreaWidth + x_diff)))
5151 #if defined(DEBUG_ILC_KEYEVENTS)
5152 D(bug("[IconList] %s: UP: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5153 #endif
5154 break;
5158 else
5160 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5162 #if defined(DEBUG_ILC_KEYEVENTS)
5163 D(bug("[IconList] %s: UP: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5164 #endif
5165 break;
5169 active_entry = (struct IconEntry *)(((struct Node *)active_entry)->ln_Pred);
5172 if (!(active_entry))
5174 #if defined(DEBUG_ILC_KEYEVENTS)
5175 D(bug("[IconList] %s: UP: No Next UP Node - Getting Last visible entry ..\n", __PRETTY_FUNCTION__));
5176 #endif
5177 /* We didnt find a "next UP" entry so just use the last visible */
5178 active_entry = Node_LastVisible(&data->icld_IconList);
5181 if (active_entry)
5183 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5185 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5186 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5187 data->update_entry = active_entry;
5188 MUI_Redraw(obj, MADF_DRAWUPDATE);
5191 data->icld_FocusIcon = active_entry;
5192 break;
5194 case RAWKEY_DOWN:
5195 rawkey_handled = TRUE;
5197 #if defined(DEBUG_ILC_KEYEVENTS)
5198 D(bug("[IconList] %s: RAWKEY_DOWN\n", __PRETTY_FUNCTION__));
5199 #endif
5200 if (data->icld_FocusIcon)
5202 start_entry = data->icld_FocusIcon;
5203 #if defined(DEBUG_ILC_KEYEVENTS)
5204 D(bug("[IconList] %s: DOWN: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5205 #endif
5207 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5208 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5209 data->update_entry = start_entry;
5210 MUI_Redraw(obj, MADF_DRAWUPDATE);
5212 start_X = start_entry->ie_IconX;
5213 start_Y = start_entry->ie_IconY;
5214 #if defined(DEBUG_ILC_KEYEVENTS)
5215 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));
5216 #endif
5217 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5219 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5221 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5222 #if defined(DEBUG_ILC_KEYEVENTS)
5223 D(bug("[IconList] %s: DOWN: adjusted start_X for grid = %d\n", __PRETTY_FUNCTION__, start_X));
5224 #endif
5228 if ((active_entry = Node_NextVisible(start_entry)) &&
5229 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5231 #if defined(DEBUG_ILC_KEYEVENTS)
5232 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));
5233 #endif
5234 active_Y = active_entry->ie_IconY;
5236 if (active_Y == start_Y)
5239 #if defined(DEBUG_ILC_KEYEVENTS)
5240 D(bug("[IconList] %s: DOWN: active_entry is on our row (not at the edge)\n", __PRETTY_FUNCTION__));
5241 #endif
5242 entry_next = active_entry;
5243 next_X = entry_next->ie_IconX;
5244 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5246 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5247 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5251 #if defined(DEBUG_ILC_KEYEVENTS)
5252 D(bug("[IconList] %s: DOWN: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5253 #endif
5256 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5258 #if defined(DEBUG_ILC_KEYEVENTS)
5259 D(bug("[IconList] %s: DOWN: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5260 #endif
5261 DoMethod(obj, MUIM_IconList_UnselectAll);
5264 #if defined(DEBUG_ILC_KEYEVENTS)
5265 D(bug("[IconList] %s: DOWN: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5266 #endif
5267 if (!(active_entry))
5269 // If nothing is selected we will use the First visible entry ..
5270 active_entry = Node_FirstVisible(&data->icld_IconList);
5271 start_X = active_entry->ie_IconX;
5272 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5274 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5275 start_X = start_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5277 start_Y = active_entry->ie_IconY;
5280 while (active_entry != NULL)
5282 #if defined(DEBUG_ILC_KEYEVENTS)
5283 D(bug("[IconList] %s: DOWN: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5284 #endif
5285 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
5287 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5288 break;
5290 else
5292 active_X = active_entry->ie_IconX;
5294 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5296 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5297 x_diff = ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5299 active_Y = active_entry->ie_IconY;
5301 if (start_entry)
5303 if (entry_next)
5305 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5306 (active_Y > start_Y) &&
5307 (((active_X - x_diff) >= start_X ) &&
5308 ((active_X - x_diff) <= (start_X + start_entry->ie_AreaWidth + (x_diff*2)))))
5310 #if defined(DEBUG_ILC_KEYEVENTS)
5311 D(bug("[IconList] %s: DOWN: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5312 #endif
5313 break;
5315 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
5317 #if defined(DEBUG_ILC_KEYEVENTS)
5318 D(bug("[IconList] %s: DOWN: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
5319 #endif
5320 start_X = entry_next->ie_IconX;
5321 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5323 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5324 start_X = start_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5327 if ((entry_next = (struct IconEntry *)Node_NextVisible(entry_next)))
5329 if (entry_next->ie_IconX < start_X)
5330 entry_next = NULL;
5331 else
5333 next_X = entry_next->ie_IconX;
5334 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5336 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5337 next_X = next_X + ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5341 start_Y = 0;
5342 #if defined(DEBUG_ILC_KEYEVENTS)
5343 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));
5344 #endif
5345 active_entry = Node_FirstVisible(&data->icld_IconList);
5348 else
5350 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5351 (active_Y > start_Y) &&
5352 (active_X > start_X - 1))
5354 #if defined(DEBUG_ILC_KEYEVENTS)
5355 D(bug("[IconList] %s: DOWN: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5356 #endif
5357 break;
5361 else
5363 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5365 #if defined(DEBUG_ILC_KEYEVENTS)
5366 D(bug("[IconList] %s: DOWN: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5367 #endif
5368 break;
5372 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5375 if (!(active_entry))
5377 #if defined(DEBUG_ILC_KEYEVENTS)
5378 D(bug("[IconList] %s: DOWN: No Next DOWN Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
5379 #endif
5380 /* We didnt find a "next DOWN" entry so just use the first visible */
5381 active_entry = Node_FirstVisible(&data->icld_IconList);
5384 if (active_entry)
5386 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5388 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5389 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5390 data->update_entry = active_entry;
5391 MUI_Redraw(obj, MADF_DRAWUPDATE);
5394 data->icld_FocusIcon = active_entry;
5395 break;
5397 case RAWKEY_LEFT:
5398 rawkey_handled = TRUE;
5400 #if defined(DEBUG_ILC_KEYEVENTS)
5401 D(bug("[IconList] %s: RAWKEY_LEFT\n", __PRETTY_FUNCTION__));
5402 #endif
5403 if (data->icld_FocusIcon)
5405 start_entry = data->icld_FocusIcon;
5406 #if defined(DEBUG_ILC_KEYEVENTS)
5407 D(bug("[IconList] %s: LEFT: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5408 #endif
5410 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5411 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5412 data->update_entry = start_entry;
5413 MUI_Redraw(obj, MADF_DRAWUPDATE);
5415 start_X = start_entry->ie_IconX;
5416 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5418 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5419 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5421 start_Y = start_entry->ie_IconY;
5423 #if defined(DEBUG_ILC_KEYEVENTS)
5424 D(bug("[IconList] %s: LEFT: start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5425 #endif
5427 if (!(active_entry = Node_NextVisible(start_entry)) && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5429 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5430 #if defined(DEBUG_ILC_KEYEVENTS)
5431 D(bug("[IconList] %s: LEFT: Start at the beginning (Active @ 0x%p) using entry X + Width\n", __PRETTY_FUNCTION__, active_entry));
5432 #endif
5433 start_X = start_X + start_entry->ie_AreaWidth;
5434 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5436 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5437 start_X = start_X + ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5440 start_Y = 0;
5441 entry_next = NULL;
5443 else if (active_entry && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5445 #if defined(DEBUG_ILC_KEYEVENTS)
5446 D(bug("[IconList] %s: LEFT: Active @ 0x%p, X %d\n", __PRETTY_FUNCTION__, active_entry, active_entry->ie_IconX));
5447 #endif
5448 if ((entry_next = Node_NextVisible(start_entry)))
5450 #if defined(DEBUG_ILC_KEYEVENTS)
5451 D(bug("[IconList] %s: LEFT: Next @ 0x%p, X %d\n", __PRETTY_FUNCTION__, entry_next, entry_next->ie_IconX));
5452 #endif
5454 if (entry_next->ie_IconX < start_X)
5455 entry_next = NULL;
5456 else
5458 next_X = entry_next->ie_IconX;
5459 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5461 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5462 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5467 #if defined(DEBUG_ILC_KEYEVENTS)
5468 D(bug("[IconList] %s: LEFT: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5469 #endif
5472 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5474 #if defined(DEBUG_ILC_KEYEVENTS)
5475 D(bug("[IconList] %s: LEFT: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5476 #endif
5477 DoMethod(obj, MUIM_IconList_UnselectAll);
5480 #if defined(DEBUG_ILC_KEYEVENTS)
5481 D(bug("[IconList] %s: LEFT: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5482 #endif
5484 if (!(active_entry))
5486 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5489 while (active_entry != NULL)
5491 #if defined(DEBUG_ILC_KEYEVENTS)
5492 D(bug("[IconList] %s: LEFT: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5493 #endif
5494 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
5496 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5497 break;
5499 else
5501 LONG active_entry_X = active_entry->ie_IconX;
5502 LONG active_entry_Y;
5503 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5505 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5506 active_entry_X = active_entry_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5508 active_entry_Y = active_entry->ie_IconY;
5510 if (start_entry)
5512 if (entry_next)
5514 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5515 (active_entry_Y > start_Y) &&
5516 ((active_entry_X > start_X - 1) &&
5517 (active_entry_X < next_X)))
5519 #if defined(DEBUG_ILC_KEYEVENTS)
5520 D(bug("[IconList] %s: LEFT: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5521 #endif
5522 break;
5524 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
5526 #if defined(DEBUG_ILC_KEYEVENTS)
5527 D(bug("[IconList] %s: LEFT: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
5528 #endif
5529 start_X = entry_next->ie_IconX;
5530 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5532 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5533 start_X = start_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5536 if ((entry_next = Node_NextVisible(entry_next)))
5538 if (entry_next->ie_IconX < start_X)
5539 entry_next = NULL;
5540 else
5542 next_X = entry_next->ie_IconX;
5543 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5545 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5546 next_X = next_X + ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
5550 start_Y = 0;
5551 #if defined(DEBUG_ILC_KEYEVENTS)
5552 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));
5553 #endif
5554 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5557 else
5559 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5560 (active_entry_Y > start_Y) &&
5561 (active_entry_X > start_X - 1))
5563 #if defined(DEBUG_ILC_KEYEVENTS)
5564 D(bug("[IconList] %s: LEFT: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5565 #endif
5566 break;
5570 else
5572 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5574 #if defined(DEBUG_ILC_KEYEVENTS)
5575 D(bug("[IconList] %s: LEFT: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5576 #endif
5577 break;
5581 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5584 if (!(active_entry))
5586 #if defined(DEBUG_ILC_KEYEVENTS)
5587 D(bug("[IconList] %s: LEFT: No Next LEFT Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
5588 #endif
5589 /* We didnt find a "next LEFT" entry so just use the last visible */
5590 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5591 while ((active_entry != NULL) &&(!(active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
5593 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5597 if (active_entry)
5599 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5601 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5602 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5603 data->update_entry = active_entry;
5604 MUI_Redraw(obj, MADF_DRAWUPDATE);
5607 data->icld_FocusIcon = active_entry;
5608 break;
5610 case RAWKEY_RIGHT:
5611 rawkey_handled = TRUE;
5613 #if defined(DEBUG_ILC_KEYEVENTS)
5614 D(bug("[IconList] %s: RAWKEY_RIGHT\n", __PRETTY_FUNCTION__));
5615 #endif
5617 if (data->icld_FocusIcon)
5619 start_entry = data->icld_FocusIcon;
5620 #if defined(DEBUG_ILC_KEYEVENTS)
5621 D(bug("[IconList] %s: RIGHT: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
5622 #endif
5623 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5624 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5625 data->update_entry = start_entry;
5626 MUI_Redraw(obj, MADF_DRAWUPDATE);
5628 start_X = start_entry->ie_IconX;
5629 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5631 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5632 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5634 start_Y = start_entry->ie_IconY;
5636 #if defined(DEBUG_ILC_KEYEVENTS)
5637 D(bug("[IconList] %s: RIGHT: start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5638 #endif
5639 if (!(active_entry = Node_NextVisible(start_entry)) && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5641 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5642 #if defined(DEBUG_ILC_KEYEVENTS)
5643 D(bug("[IconList] %s: RIGHT: Start at the beginning (Active @ 0x%p) using entry X + Width\n", __PRETTY_FUNCTION__, active_entry));
5644 #endif
5645 start_X = 0;
5646 start_Y = start_Y + start_entry->ie_AreaHeight;
5647 entry_next = NULL;
5649 else if (active_entry && (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5651 #if defined(DEBUG_ILC_KEYEVENTS)
5652 D(bug("[IconList] %s: RIGHT: Active @ 0x%p, X %d\n", __PRETTY_FUNCTION__, active_entry, active_entry->ie_IconX));
5653 #endif
5654 if ((entry_next = Node_NextVisible(start_entry)))
5656 #if defined(DEBUG_ILC_KEYEVENTS)
5657 D(bug("[IconList] %s: RIGHT: Next @ 0x%p, X %d\n", __PRETTY_FUNCTION__, entry_next, entry_next->ie_IconX));
5658 #endif
5660 if (entry_next->ie_IconY < start_Y)
5661 entry_next = NULL;
5662 else
5663 next_Y = entry_next->ie_IconY;
5666 #if defined(DEBUG_ILC_KEYEVENTS)
5667 D(bug("[IconList] %s: RIGHT: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5668 #endif
5671 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5673 #if defined(DEBUG_ILC_KEYEVENTS)
5674 D(bug("[IconList] %s: RIGHT: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5675 #endif
5676 DoMethod(obj, MUIM_IconList_UnselectAll);
5679 #if defined(DEBUG_ILC_KEYEVENTS)
5680 D(bug("[IconList] %s: RIGHT: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5681 #endif
5683 if (!(active_entry))
5685 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5688 while (active_entry != NULL)
5690 #if defined(DEBUG_ILC_KEYEVENTS)
5691 D(bug("[IconList] %s: RIGHT: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5692 #endif
5693 if (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5695 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5696 break;
5698 else
5700 LONG active_entry_X = active_entry->ie_IconX;
5701 LONG active_entry_Y;
5702 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5704 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5705 active_entry_X = active_entry_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5707 active_entry_Y = active_entry->ie_IconY;
5709 if (start_entry)
5711 if (entry_next)
5713 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5714 (active_entry_X > start_X) &&
5715 ((active_entry_Y > start_Y - 1) &&
5716 (active_entry_Y < next_Y)))
5718 #if defined(DEBUG_ILC_KEYEVENTS)
5719 D(bug("[IconList] %s: RIGHT: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5720 #endif
5721 break;
5723 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
5725 #if defined(DEBUG_ILC_KEYEVENTS)
5726 D(bug("[IconList] %s: RIGHT: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
5727 #endif
5728 start_Y = entry_next->ie_IconY;
5730 if ((entry_next = Node_NextVisible(entry_next)))
5732 if (entry_next->ie_IconY < start_Y)
5733 entry_next = NULL;
5734 else
5736 next_Y = entry_next->ie_IconY;
5739 start_Y = 0;
5740 #if defined(DEBUG_ILC_KEYEVENTS)
5741 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));
5742 #endif
5743 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5746 else
5748 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5749 (active_entry_X > start_X) &&
5750 (active_entry_Y > start_Y - 1))
5752 #if defined(DEBUG_ILC_KEYEVENTS)
5753 D(bug("[IconList] %s: RIGHT: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5754 #endif
5755 break;
5759 else
5761 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5763 #if defined(DEBUG_ILC_KEYEVENTS)
5764 D(bug("[IconList] %s: RIGHT: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5765 #endif
5766 break;
5770 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5773 if (!(active_entry))
5775 #if defined(DEBUG_ILC_KEYEVENTS)
5776 D(bug("[IconList] %s: RIGHT: No Next RIGHT Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
5777 #endif
5778 /* We didnt find a "next RIGHT" entry so just use the first visible */
5779 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5780 while ((active_entry != NULL) &&(!(active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
5782 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5786 if (active_entry)
5788 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5790 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5791 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5792 data->update_entry = active_entry;
5793 MUI_Redraw(obj, MADF_DRAWUPDATE);
5796 data->icld_FocusIcon = active_entry;
5797 break;
5799 case RAWKEY_HOME:
5800 rawkey_handled = TRUE;
5802 #if defined(DEBUG_ILC_KEYEVENTS)
5803 D(bug("[IconList] %s: RAWKEY_HOME\n", __PRETTY_FUNCTION__));
5804 #endif
5806 if (data->icld_FocusIcon)
5808 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5809 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5810 data->update_entry = data->icld_FocusIcon;
5811 MUI_Redraw(obj, MADF_DRAWUPDATE);
5814 active_entry = Node_FirstVisible(&data->icld_IconList);
5816 if ((active_entry) && (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
5818 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5819 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5820 data->update_entry = active_entry;
5821 MUI_Redraw(obj, MADF_DRAWUPDATE);
5823 data->icld_FocusIcon = active_entry;
5824 break;
5826 case RAWKEY_END:
5827 rawkey_handled = TRUE;
5829 #if defined(DEBUG_ILC_KEYEVENTS)
5830 D(bug("[IconList] %s: RAWKEY_END\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_LastVisible(&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;
5854 if (rawkey_handled) return MUI_EventHandlerRC_Eat;
5856 break;
5858 case IDCMP_MOUSEBUTTONS:
5859 #if defined(DEBUG_ILC_EVENTS)
5860 D(bug("[IconList] %s: IDCMP_MOUSEBUTTONS\n", __PRETTY_FUNCTION__));
5861 #endif
5862 if (message->imsg->Code == SELECTDOWN)
5864 /* Check if mouse pressed on iconlist area */
5865 if (mx >= 0 && mx < _width(obj) && my >= 0 && my < _height(obj))
5867 BOOL doubleclicked = FALSE; /* both icon and empty space */
5868 struct IconEntry *node = NULL;
5869 struct IconEntry *new_selected = NULL;
5871 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
5873 /* LIST-VIEW HANDLING */
5875 LONG clickColumn = -1;
5877 LONG x = _mleft(obj) - data->icld_ViewX + LINE_SPACING_LEFT;
5878 LONG index, w, i;
5880 /* Find column in which click happened */
5881 for(i = 0; i < NUM_COLUMNS; i++)
5883 index = data->icld_LVMAttribs->lmva_ColumnPos[i];
5885 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
5887 w = data->icld_LVMAttribs->lmva_ColumnWidth[index];
5889 if ((mx >= x) && (mx < x + w))
5891 clickColumn = index;
5892 break;
5894 x += w;
5897 if (((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0) && (my <= data->icld_LVMAttribs->lmva_HeaderHeight))
5899 /* Click on header, update list */
5900 data->icld_LVMAttribs->lmva_LastSelectedColumn = clickColumn;
5902 data->icld_UpdateMode = UPDATE_HEADERENTRY;
5903 data->update_entry = (APTR)(IPTR)clickColumn;
5905 MUI_Redraw(obj, MADF_DRAWUPDATE);
5908 else
5910 LONG current = 0, index = (my - data->icld_LVMAttribs->lmva_HeaderHeight + data->icld_ViewY) / data->icld_LVMAttribs->lmva_RowHeight;
5912 /* Check if clicked on entry */
5913 ForeachNode(&data->icld_IconList, node)
5915 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5917 /* Is this node clicked? */
5918 if (current == index)
5920 new_selected = node;
5921 break;
5924 current++;
5928 /* Handle actions */
5929 IconList_HandleNewIconSelection(CLASS, obj, message, new_selected, &doubleclicked);
5932 else
5934 /* ICON-VIEW HANDLING */
5936 struct Rectangle rect;
5938 /* Check if clicked on entry */
5939 #if defined(__AROS__)
5940 ForeachNode(&data->icld_IconList, node)
5941 #else
5942 Foreach_Node(&data->icld_IconList, node);
5943 #endif
5945 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5947 /* Is this node clicked? */
5948 rect.MinX = node->ie_IconX;
5949 rect.MaxX = node->ie_IconX + node->ie_AreaWidth - 1;
5950 rect.MinY = node->ie_IconY;
5951 rect.MaxY = node->ie_IconY + node->ie_AreaHeight - 1;
5953 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
5954 (node->ie_AreaWidth < data->icld_IconAreaLargestWidth))
5956 rect.MinX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
5957 rect.MaxX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
5960 if ((((mx + data->icld_ViewX) >= rect.MinX) && ((mx + data->icld_ViewX) <= rect.MaxX )) &&
5961 (((my + data->icld_ViewY) >= rect.MinY) && ((my + data->icld_ViewY) <= rect.MaxY )))
5963 new_selected = node;
5964 #if defined(DEBUG_ILC_EVENTS)
5965 D(bug("[IconList] %s: Entry '%s' clicked on ..\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
5966 #endif
5967 break;
5972 /* Handle actions */
5973 IconList_HandleNewIconSelection(CLASS, obj, message, new_selected, &doubleclicked);
5976 if (new_selected && (new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED))
5977 data->icld_SelectionLastClicked = new_selected;
5978 else
5979 data->icld_SelectionLastClicked = NULL;
5981 data->click_x = mx;
5982 data->click_y = my;
5984 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
5986 data->icld_ClickEvent.shift = !!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT));
5987 data->icld_ClickEvent.entry = data->icld_SelectionLastClicked ? &data->icld_SelectionLastClicked->ie_IconListEntry : NULL;
5988 SET(obj, MUIA_IconList_Clicked, (IPTR)&data->icld_ClickEvent);
5990 if (doubleclicked)
5992 SET(obj, MUIA_IconList_DoubleClick, TRUE);
5995 if ((!data->mouse_pressed) &&
5996 (!doubleclicked || (doubleclicked && (data->icld_SelectionLastClicked == NULL))))
5998 data->last_secs = message->imsg->Seconds;
5999 data->last_mics = message->imsg->Micros;
6001 /* After a double click you often open a new window
6002 * and since Zune doesn't not support the faking
6003 * of SELECTUP events only change the Events
6004 * if not doubleclicked on an icon */
6006 data->mouse_pressed |= LEFT_BUTTON;
6008 /* Start listening to mouse events */
6009 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
6011 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6012 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
6013 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6017 return MUI_EventHandlerRC_Eat;
6020 else if (message->imsg->Code == MIDDLEDOWN)
6022 if (!data->mouse_pressed)
6024 data->mouse_pressed |= MIDDLE_BUTTON;
6026 data->click_x = data->icld_ViewX + mx;
6027 data->click_y = data->icld_ViewY + my;
6029 /* Start listening to mouse events */
6030 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
6032 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6033 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
6034 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6038 else
6040 if (message->imsg->Code == SELECTUP)
6042 if (data->icld_LassoActive == TRUE)
6044 #if defined(DEBUG_ILC_EVENTS) || defined(DEBUG_ILC_LASSO)
6045 D(bug("[IconList] %s: Removing Lasso\n", __PRETTY_FUNCTION__));
6046 #endif
6047 /* End Lasso-selection */
6048 struct Rectangle old_lasso;
6049 struct IconEntry *node = NULL;
6050 struct Window *thisWindow = NULL;
6052 /* Stop handling INTUITICKS */
6053 GET(obj, MUIA_Window, &thisWindow);
6054 if (thisWindow)
6056 ModifyIDCMP(thisWindow, (thisWindow->IDCMPFlags & ~(IDCMP_INTUITICKS)));
6057 if ((data->ehn.ehn_Events & IDCMP_INTUITICKS))
6059 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6060 data->ehn.ehn_Events &= ~IDCMP_INTUITICKS;
6061 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6064 /* Clear Lasso Frame.. */
6065 GetAbsoluteLassoRect(data, &old_lasso);
6066 IconList_InvertLassoOutlines(obj, data, &old_lasso);
6068 data->icld_LassoActive = FALSE;
6070 /* Remove Lasso flag from affected icons.. */
6071 #if defined(__AROS__)
6072 ForeachNode(&data->icld_IconList, node)
6073 #else
6074 Foreach_Node(&data->icld_IconList, node);
6075 #endif
6077 if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
6079 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
6082 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
6084 else if (data->icld_LVMAttribs->lmva_LastSelectedColumn != -1)
6086 ULONG orig_sortflags = data->icld_SortFlags;
6088 if (data->icld_LVMAttribs->lmva_SortColumn == data->icld_LVMAttribs->lmva_LastSelectedColumn)
6090 if (data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
6091 data->icld_SortFlags &= ~MUIV_IconList_Sort_Reverse;
6092 else
6093 data->icld_SortFlags |= MUIV_IconList_Sort_Reverse;
6096 switch (data->icld_LVMAttribs->lmva_LastSelectedColumn)
6098 case INDEX_NAME:
6099 data->icld_SortFlags &= ~MUIV_IconList_Sort_Orders;
6100 data->icld_SortFlags |= MUIV_IconList_Sort_ByName;
6101 break;
6103 case INDEX_SIZE:
6104 data->icld_SortFlags &= ~MUIV_IconList_Sort_Orders;
6105 data->icld_SortFlags |= MUIV_IconList_Sort_BySize;
6106 break;
6108 case INDEX_LASTACCESS:
6109 data->icld_SortFlags &= ~MUIV_IconList_Sort_Orders;
6110 data->icld_SortFlags |= MUIV_IconList_Sort_ByDate;
6111 break;
6114 if (orig_sortflags != data->icld_SortFlags)
6116 data->icld_LVMAttribs->lmva_SortColumn = data->icld_LVMAttribs->lmva_LastSelectedColumn;
6118 data->icld_LVMAttribs->lmva_LastSelectedColumn = -1;
6120 DoMethod(obj, MUIM_IconList_Sort);
6124 data->mouse_pressed &= ~LEFT_BUTTON;
6127 if (message->imsg->Code == MIDDLEUP)
6129 data->mouse_pressed &= ~MIDDLE_BUTTON;
6132 /* Stop listening to mouse move events is no buttons pressed */
6133 if ((data->ehn.ehn_Events & IDCMP_MOUSEMOVE) && !data->mouse_pressed)
6135 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6136 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
6137 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6140 break;
6142 case IDCMP_INTUITICKS:
6144 #if defined(DEBUG_ILC_EVENTS)
6145 D(bug("[IconList] %s: IDCMP_INTUITICKS (%d, %d)\n", __PRETTY_FUNCTION__, mx, my));
6146 #endif
6147 if ((data->icld_LassoActive == FALSE)||(!(data->mouse_pressed & LEFT_BUTTON)))
6149 break;
6151 if (((mx >= 0) && (mx <= _mwidth(obj))) &&
6152 ((my >= 0) && (my <= _mheight(obj))))
6153 break;
6156 case IDCMP_MOUSEMOVE:
6157 #if defined(DEBUG_ILC_EVENTS)
6158 D(bug("[IconList] %s: IDCMP_MOUSEMOVE\n", __PRETTY_FUNCTION__));
6159 #endif
6160 if (data->mouse_pressed & LEFT_BUTTON)
6162 LONG move_x = mx;
6163 LONG move_y = my;
6165 if (data->icld_SelectionLastClicked && (data->icld_LassoActive == FALSE) &&
6166 ((abs(move_x - data->click_x) >= 2) || (abs(move_y - data->click_y) >= 2)))
6168 LONG touch_x, touch_y;
6170 /* Entry(s) being dragged .... */
6171 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
6172 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
6173 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
6175 data->mouse_pressed &= ~LEFT_BUTTON;
6177 /* Pass view relative coords */
6178 touch_x = move_x + data->icld_ViewX;
6179 touch_y = move_y + data->icld_ViewY;
6180 DoMethod(obj,MUIM_DoDrag, touch_x, touch_y, 0);
6182 else if (data->icld_LassoActive == TRUE)
6184 #if defined(DEBUG_ILC_EVENTS) || defined(DEBUG_ILC_LASSO)
6185 D(bug("[IconList] %s: Update Lasso\n", __PRETTY_FUNCTION__));
6186 #endif
6187 /* Lasso active */
6188 struct Rectangle new_lasso,
6189 old_lasso;
6190 struct Rectangle iconrect;
6192 struct IconEntry *node = NULL;
6193 // struct IconEntry *new_selected = NULL;
6195 /* Remove previous Lasso frame */
6196 GetAbsoluteLassoRect(data, &old_lasso);
6197 IconList_InvertLassoOutlines(obj, data, &old_lasso);
6199 /* if the mouse leaves our visible area scroll the view */
6200 if (mx < 0 || mx >= _mwidth(obj) || my < 0 || my >= _mheight(obj))
6202 LONG newleft = data->icld_ViewX;
6203 LONG newtop = data->icld_ViewY;
6205 if (mx >= _mwidth(obj)) newleft += (mx - _mwidth(obj));
6206 else if (mx < 0) newleft += mx;
6207 if (my >= _mheight(obj)) newtop += (my - _mheight(obj));
6208 else if (my < 0) newtop += my;
6210 if (newleft + _mwidth(obj) > data->icld_AreaWidth) newleft = data->icld_AreaWidth - _mwidth(obj);
6211 if (newleft < 0) newleft = 0;
6213 if (newtop + _mheight(obj) > data->icld_AreaHeight) newtop = data->icld_AreaHeight - _mheight(obj);
6214 if (newtop < 0) newtop = 0;
6216 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
6218 SetAttrs(obj, MUIA_Virtgroup_Left, newleft, MUIA_Virtgroup_Top, newtop, TAG_DONE);
6222 /* update Lasso coordinates */
6223 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
6224 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
6226 /* get absolute Lasso coordinates */
6227 GetAbsoluteLassoRect(data, &new_lasso);
6229 LONG current = 0, startIndex = 0, endIndex = 0;
6231 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6233 LONG minY = data->icld_LassoRectangle.MinY,
6234 maxY = data->icld_LassoRectangle.MaxY;
6236 if (minY > maxY)
6238 minY ^= maxY;
6239 maxY ^= minY;
6240 minY ^= maxY;
6243 startIndex = ((minY + 1) - data->icld_LVMAttribs->lmva_HeaderHeight) / data->icld_LVMAttribs->lmva_RowHeight;
6244 endIndex = ((maxY - 1) - data->icld_LVMAttribs->lmva_HeaderHeight) / data->icld_LVMAttribs->lmva_RowHeight;
6247 #if defined(__AROS__)
6248 ForeachNode(&data->icld_IconList, node)
6249 #else
6250 Foreach_Node(&data->icld_IconList, node);
6251 #endif
6253 IPTR update_entry = (IPTR)NULL;
6255 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6257 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6259 update_entry = FALSE;
6261 if ((current >= startIndex) && (current <= endIndex))
6263 //Entry is inside our lasso ..
6264 if (!(node->ie_Flags & ICONENTRY_FLAG_LASSO))
6266 /* check if entry was already selected before */
6267 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6269 Remove(&node->ie_SelectionNode);
6270 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6272 else
6274 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6275 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6277 node->ie_Flags |= ICONENTRY_FLAG_LASSO;
6278 update_entry = (IPTR)node;
6281 else if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
6283 //Entry is no longer inside our lasso - revert its selected state
6284 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6286 Remove(&node->ie_SelectionNode);
6287 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6289 else
6291 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6292 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6294 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
6295 update_entry = (IPTR)node;
6298 current++;
6301 else
6303 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6305 iconrect.MinX = node->ie_IconX;
6306 iconrect.MaxX = node->ie_IconX + node->ie_AreaWidth - 1;
6307 iconrect.MinY = node->ie_IconY;
6308 iconrect.MaxY = node->ie_IconY + node->ie_AreaHeight - 1;
6309 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
6310 (node->ie_AreaWidth < data->icld_IconAreaLargestWidth))
6312 iconrect.MinX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
6313 iconrect.MaxX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
6316 if ((((new_lasso.MaxX + data->icld_ViewX) >= iconrect.MinX) && ((new_lasso.MinX + data->icld_ViewX) <= iconrect.MaxX)) &&
6317 (((new_lasso.MaxY + data->icld_ViewY) >= iconrect.MinY) && ((new_lasso.MinY + data->icld_ViewY) <= iconrect.MaxY)))
6319 //Entry is inside our lasso ..
6320 if (!(node->ie_Flags & ICONENTRY_FLAG_LASSO))
6322 /* check if entry was already selected before */
6323 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6325 Remove(&node->ie_SelectionNode);
6326 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6328 else
6330 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6331 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6333 node->ie_Flags |= ICONENTRY_FLAG_LASSO;
6334 update_entry = (IPTR)node;
6337 else if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
6339 //Entry is no longer inside our lasso - revert its selected state
6340 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
6342 Remove(&node->ie_SelectionNode);
6343 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6345 else
6347 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6348 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6350 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
6351 update_entry = (IPTR)node;
6355 if (update_entry)
6357 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
6358 data->update_entry = (struct IconEntry *)update_entry;
6359 MUI_Redraw(obj, MADF_DRAWUPDATE);
6362 /* Draw Lasso frame */
6363 IconList_InvertLassoOutlines(obj, data, &new_lasso);
6366 return MUI_EventHandlerRC_Eat;
6368 else if (data->mouse_pressed & MIDDLE_BUTTON)
6370 /* Content is being scrolled */
6371 LONG newleft, newtop;
6373 newleft = data->click_x - mx;
6374 newtop = data->click_y - my;
6376 if (newleft + _mwidth(obj) > data->icld_AreaWidth) newleft = data->icld_AreaWidth - _mwidth(obj);
6377 if (newleft < 0) newleft = 0;
6379 if (newtop + _mheight(obj) > data->icld_AreaHeight) newtop = data->icld_AreaHeight - _mheight(obj);
6380 if (newtop < 0) newtop = 0;
6382 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
6384 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
6385 MUIA_Virtgroup_Top, newtop,
6386 TAG_DONE);
6389 return MUI_EventHandlerRC_Eat;
6392 break;
6396 return 0;
6400 ///MUIM_IconList_NextIcon()
6401 /**************************************************************************
6402 MUIM_IconList_NextIcon
6403 **************************************************************************/
6404 IPTR IconList__MUIM_IconList_NextIcon(struct IClass *CLASS, Object *obj, struct MUIP_IconList_NextIcon *message)
6406 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6407 struct IconEntry *node = NULL;
6408 struct IconList_Entry *ent = NULL;
6409 IPTR node_successor = (IPTR)NULL;
6411 if (message->entry == NULL) return (IPTR)NULL;
6412 ent = *message->entry;
6414 #if defined(DEBUG_ILC_FUNCS)
6415 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6416 #endif
6418 if ((IPTR)ent == (IPTR)MUIV_IconList_NextIcon_Start)
6420 D(bug("[IconList] %s: Finding First Entry ..\n", __PRETTY_FUNCTION__));
6421 if (message->nextflag == MUIV_IconList_NextIcon_Selected)
6423 node = (struct IconEntry *)GetHead(&data->icld_SelectionList);
6424 if (node != NULL)
6426 node = (struct IconEntry *)((IPTR)node - ((IPTR)&node->ie_SelectionNode - (IPTR)node));
6429 else if (message->nextflag == MUIV_IconList_NextIcon_Visible)
6431 node = (struct IconEntry *)GetHead(&data->icld_IconList);
6432 while (node != NULL)
6434 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6435 break;
6437 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6441 else if ((IPTR)ent != (IPTR)MUIV_IconList_NextIcon_End)
6443 node = (struct IconEntry *)((IPTR)ent - ((IPTR)&node->ie_IconListEntry - (IPTR)node));
6444 if (message->nextflag == MUIV_IconList_NextIcon_Selected)
6446 node_successor = (IPTR)GetSucc(&node->ie_SelectionNode);
6447 if (node_successor != (IPTR)NULL)
6448 node = (struct IconEntry *)((IPTR)node_successor - ((IPTR)&node->ie_SelectionNode - (IPTR)node));
6449 else
6451 D(bug("[IconList] %s: GetSucc() == NULL\n", __PRETTY_FUNCTION__));
6452 node = NULL;
6455 else if (message->nextflag == MUIV_IconList_NextIcon_Visible)
6457 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6458 while (node != NULL)
6460 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6461 break;
6463 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6468 if (node == NULL)
6470 D(bug("[IconList] %s: Returning MUIV_IconList_NextIcon_End\n", __PRETTY_FUNCTION__));
6472 *message->entry = (struct IconList_Entry *)MUIV_IconList_NextIcon_End;
6474 else
6476 D(bug("[IconList] %s: Returning entry for '%s'\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
6478 *message->entry = &node->ie_IconListEntry;
6481 return (IPTR)NULL;
6485 ///MUIM_IconList_GetIconPrivate()
6486 /**************************************************************************
6487 MUIM_IconList_GetIconPrivate
6488 **************************************************************************/
6489 IPTR IconList__MUIM_IconList_GetIconPrivate(struct IClass *CLASS, Object *obj, struct MUIP_IconList_GetIconPrivate *message)
6491 // struct IconList_DATA *data = INST_DATA(CLASS, obj);
6492 struct IconEntry *node = NULL;
6494 if (message->entry == NULL) return (IPTR)NULL;
6496 node = (struct IconEntry *)((IPTR)message->entry - ((IPTR)&node->ie_IconListEntry - (IPTR)node));
6498 return (IPTR)node;
6501 ///MUIM_CreateDragImage()
6502 /**************************************************************************
6503 MUIM_CreateDragImage
6504 **************************************************************************/
6505 IPTR IconList__MUIM_CreateDragImage(struct IClass *CLASS, Object *obj, struct MUIP_CreateDragImage *message)
6507 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6508 struct MUI_DragImage *img = NULL;
6509 LONG first_x = -1,
6510 first_y = -1;
6511 BOOL transp = XGET(obj, MUIA_IconList_DragImageTransparent);
6513 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6514 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6515 #endif
6517 if (!(data->icld_SelectionLastClicked))
6518 DoSuperMethodA(CLASS, obj, (Msg)message);
6520 if ((img = (struct MUI_DragImage *)AllocVec(sizeof(struct MUIP_CreateDragImage), MEMF_CLEAR)))
6522 struct Node *node = NULL;
6523 struct IconEntry *entry = NULL;
6525 #if defined(CREATE_FULL_DRAGIMAGE)
6526 #if defined(__AROS__)
6527 ForeachNode(&data->icld_SelectionList, node)
6528 #else
6529 Foreach_Node(&data->icld_SelectionList, node);
6530 #endif
6532 entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
6533 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) && (entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
6535 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) != ICONLIST_DISP_MODELIST)
6537 if ((first_x == -1) || ((first_x != -1) && (entry->ie_IconX < first_x))) first_x = entry->ie_IconX;
6538 if ((first_y == -1) || ((first_y != -1) && (entry->ie_IconY < first_y))) first_y = entry->ie_IconY;
6540 if (data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH)
6542 if ((entry->ie_IconX + entry->ie_AreaWidth) > img->width) img->width = entry->ie_IconX + entry->ie_AreaWidth;
6543 if ((entry->ie_IconY + entry->ie_AreaHeight) > img->height) img->height = entry->ie_IconY + entry->ie_AreaHeight;
6546 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
6548 if ((entry->ie_IconX + data->icld_IconAreaLargestWidth) > img->width) img->width = entry->ie_IconX + data->icld_IconAreaLargestWidth;
6549 if ((entry->ie_IconY + data->icld_IconAreaLargestHeight) > img->height) img->height = entry->ie_IconY + data->icld_IconAreaLargestHeight;
6552 else
6554 img->height += data->icld_LVMAttribs->lmva_RowHeight;
6558 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6560 first_x = 0;
6561 first_y = -message->touchy;
6562 img->width = data->icld_LVMAttribs->lmva_ColumnWidth[data->icld_LVMAttribs->lmva_ColumnPos[INDEX_TYPE]] +
6563 data->icld_LVMAttribs->lmva_ColumnWidth[data->icld_LVMAttribs->lmva_ColumnPos[INDEX_NAME]];
6564 img->height += 2;
6566 else
6568 img->width = (img->width - first_x) + 2;
6569 img->height = (img->height - first_y) + 2;
6571 #else
6572 entry = data->icld_SelectionLastClicked;
6573 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6575 img->width = _mright(obj) - _mleft(obj);
6576 img->height = data->icld_LVMAttribs->lmva_RowHeight;
6577 first_x = 0;
6578 first_y = 0;
6580 else
6582 img->width = entry->ie_IconWidth;
6583 img->height = entry->ie_IconHeight;
6584 first_x = entry->ie_IconX;
6585 first_y = entry->ie_IconY;
6587 #endif
6589 if (transp)
6591 /* Request 32-bit, because the image will have alpha channel */
6592 img->bm = AllocBitMap(img->width, img->height, 32, BMF_CLEAR, NULL);
6594 else
6596 LONG depth = GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH);
6597 img->bm = AllocBitMap(img->width, img->height, depth, BMF_CLEAR, _screen(obj)->RastPort.BitMap);
6600 if (img->bm)
6602 struct RastPort temprp;
6603 InitRastPort(&temprp);
6604 temprp.BitMap = img->bm;
6605 ULONG minY = 0;
6607 #if defined(CREATE_FULL_DRAGIMAGE)
6608 ForeachNode(&data->icld_SelectionList, node)
6610 entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
6611 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) && (entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
6613 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6615 struct Rectangle field_rect;
6616 ULONG selected = entry->ie_Flags & ICONENTRY_FLAG_SELECTED;
6617 entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED; /* Drawing as not selected actually looks better */
6619 field_rect.MinX = 0; field_rect.MaxX = img->width - 1;
6620 field_rect.MinY = minY; field_rect.MaxY = field_rect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
6621 RenderEntryField(obj, data, entry, &field_rect, INDEX_TYPE, TRUE, FALSE, &temprp);
6623 field_rect.MinX = data->icld_LVMAttribs->lmva_ColumnWidth[data->icld_LVMAttribs->lmva_ColumnPos[INDEX_TYPE]] - 1;
6624 field_rect.MaxX = img->width - 1;
6625 field_rect.MinY = minY; field_rect.MaxY = field_rect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
6626 RenderEntryField(obj, data, entry, &field_rect, INDEX_NAME, FALSE, FALSE, &temprp);
6628 minY += data->icld_LVMAttribs->lmva_RowHeight;
6630 entry->ie_Flags |= selected;
6632 else
6634 LONG offsetx , offsety;
6636 IconList_GetIconImageOffsets(data, entry, &offsetx, &offsety);
6638 DrawIconStateA
6640 &temprp, entry->ie_DiskObj, NULL,
6641 (entry->ie_IconX + 1) - first_x + offsetx, (entry->ie_IconY + 1) - first_y + offsety,
6642 IDS_SELECTED,
6643 __iconList_DrawIconStateTags
6648 #else
6649 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6651 SetABPenDrMd(&temprp, _pens(obj)[MPEN_SHINE], 0, JAM1);
6652 RectFill(&temprp, 0, 0, img->width, img->height);
6654 else
6656 DrawIconStateA
6658 &temprp, entry->ie_DiskObj, NULL,
6659 0, 0,
6660 IDS_SELECTED,
6661 __iconList_DrawIconStateTags
6664 #endif
6665 if (transp)
6666 RastPortSetAlpha(&temprp, data->click_x, data->click_y, img->width, img->height, 0xC0, RPALPHAFLAT);
6667 DeinitRastPort(&temprp);
6670 /* Convert view relative coords to drag image relative. This is done because the "object" that is being
6671 * dragged is virtual (its a collection of icons) and the coords passed to DoDrag are not relative to this
6672 * "object"
6674 img->touchx = first_x + message->touchx;
6675 img->touchy = first_y + message->touchy;
6677 if (transp)
6678 img->flags = MUIF_DRAGIMAGE_SOURCEALPHA;
6679 else
6680 img->flags = 0;
6682 return (IPTR)img;
6686 ///MUIM_DeleteDragImage()
6687 /**************************************************************************
6688 MUIM_DeleteDragImage
6689 **************************************************************************/
6690 IPTR IconList__MUIM_DeleteDragImage(struct IClass *CLASS, Object *obj, struct MUIP_DeleteDragImage *message)
6692 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6694 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6695 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6696 #endif
6698 if (!(data->icld_SelectionLastClicked)) return DoSuperMethodA(CLASS,obj,(Msg)message);
6700 if (message->di)
6702 if (message->di->bm)
6703 FreeBitMap(message->di->bm);
6704 FreeVec(message->di);
6706 return (IPTR)NULL;
6710 ///MUIM_DragQuery()
6711 /**************************************************************************
6712 MUIM_DragQuery
6713 **************************************************************************/
6714 IPTR IconList__MUIM_DragQuery(struct IClass *CLASS, Object *obj, struct MUIP_DragQuery *message)
6716 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6717 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6718 #endif
6720 /* TODO: highlight the possible drop target entry .. */
6722 if (message->obj == obj)
6723 return MUIV_DragQuery_Accept;
6724 else
6726 BOOL is_iconlist = FALSE;
6727 struct IClass *msg_cl = OCLASS(message->obj);
6729 while (msg_cl)
6731 if (msg_cl == CLASS)
6733 is_iconlist = TRUE;
6734 break;
6736 msg_cl = msg_cl->cl_Super;
6738 if (is_iconlist)
6739 return MUIV_DragQuery_Accept;
6742 return MUIV_DragQuery_Refuse;
6746 ///MUIM_DragDrop()
6747 /**************************************************************************
6748 MUIM_DragDrop
6749 **************************************************************************/
6750 IPTR IconList__MUIM_DragDrop(struct IClass *CLASS, Object *obj, struct MUIP_DragDrop *message)
6752 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6754 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
6755 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6756 #endif
6758 struct IconList_Entry *entry = (IPTR)MUIV_IconList_NextIcon_Start;
6760 if (data->icld_DragDropEvent)
6762 struct IconList_Drop_SourceEntry *clean_node;
6763 #if defined(DEBUG_ILC_ICONDRAGDROP)
6764 D(bug("[IconList] %s: Cleaning existing IconList_Drop_Event @ %p\n", __PRETTY_FUNCTION__, data->icld_DragDropEvent));
6765 #endif
6766 while ((clean_node = (struct IconList_Drop_SourceEntry *)RemTail(&data->icld_DragDropEvent->drop_SourceList)) != NULL)
6768 FreeVec(clean_node->dropse_Node.ln_Name);
6769 FreeMem(clean_node, sizeof(struct IconList_Drop_SourceEntry));
6771 if (data->icld_DragDropEvent->drop_TargetPath) FreeVec(data->icld_DragDropEvent->drop_TargetPath);
6772 FreeMem(data->icld_DragDropEvent, sizeof(struct IconList_Drop_Event));
6773 data->icld_DragDropEvent = NULL;
6776 /* SANITY CHECK: Get first selected entry from SOURCE iconlist */
6777 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
6779 if ((entry) && ((IPTR)entry != MUIV_IconList_NextIcon_End))
6781 /* Ok.. atleast one entry was dropped .. */
6782 char tmp_dirbuff[256];
6783 BPTR tmp_dirlock = (BPTR) NULL;
6785 BOOL iconMove = FALSE;
6786 struct IconEntry *node = NULL;
6787 struct IconEntry *drop_target_node = NULL;
6788 STRPTR directory_path = NULL;
6789 struct IconList_Drop_Event *dragDropEvent = NULL;
6791 GET(obj, MUIA_IconDrawerList_Drawer, &directory_path);
6793 /* Properly expand the name incase it uses devices rather than volumes */
6794 if (directory_path != NULL)
6796 tmp_dirlock = Lock(directory_path, SHARED_LOCK);
6797 if (tmp_dirlock)
6799 if (NameFromLock(tmp_dirlock, tmp_dirbuff, 256) != 0)
6801 directory_path = tmp_dirbuff;
6803 UnLock(tmp_dirlock);
6806 if ((dragDropEvent = AllocMem(sizeof(struct IconList_Drop_Event), MEMF_CLEAR)) == NULL)
6808 #if defined(DEBUG_ILC_ICONDRAGDROP)
6809 D(bug("[IconList] %s: Failed to allocate IconList_Drop_Event Storage!\n", __PRETTY_FUNCTION__));
6810 #endif
6811 goto dragdropdone;
6813 #if defined(DEBUG_ILC_ICONDRAGDROP)
6814 D(bug("[IconList] %s: Allocated IconList_Drop_Event @ %p\n", __PRETTY_FUNCTION__, dragDropEvent));
6815 #endif
6817 NewList(&dragDropEvent->drop_SourceList);
6819 /* go through list and check if dropped on entry */
6820 int rowCount = 0;
6822 #if defined(__AROS__)
6823 ForeachNode(&data->icld_IconList, node)
6824 #else
6825 Foreach_Node(&data->icld_IconList, node);
6826 #endif
6828 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6830 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6832 ULONG rowTop = _mtop(obj) + (rowCount * data->icld_LVMAttribs->lmva_RowHeight);
6833 rowTop += data->icld_LVMAttribs->lmva_HeaderHeight;
6835 if (((message->x > _mleft(obj)) && (message->x < _mright(obj)))
6836 && ((message->y > rowTop) && (message->y < (rowTop + data->icld_LVMAttribs->lmva_RowHeight))))
6838 drop_target_node = node;
6839 break;
6842 rowCount++;
6845 else
6847 struct Rectangle iconbox;
6848 LONG click_x = message->x - _mleft(obj);
6849 LONG click_y = message->y - _mtop(obj);
6850 iconbox.MinX = node->ie_IconX - data->icld_ViewX;
6851 iconbox.MaxX = (node->ie_IconX + node->ie_AreaWidth) - data->icld_ViewX;
6852 iconbox.MinY = node->ie_IconY - data->icld_ViewY;
6853 iconbox.MaxY = (node->ie_IconY + node->ie_AreaHeight)- data->icld_ViewY;
6855 if ((node->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
6856 (click_x >= iconbox.MinX) &&
6857 (click_x < iconbox.MaxX) &&
6858 (click_y >= iconbox.MinY) &&
6859 (click_y < iconbox.MaxY))
6861 drop_target_node = node;
6862 break;
6867 /* Additional filter - if same window and the target entry is selected (==dragged), then it was intended as a move */
6868 if ((message->obj == obj) && (drop_target_node) && (drop_target_node->ie_Flags & ICONENTRY_FLAG_SELECTED))
6869 drop_target_node = NULL;
6871 if ((drop_target_node != NULL) &&
6872 ((drop_target_node->ie_IconListEntry.type == ST_SOFTLINK) ||
6873 (drop_target_node->ie_IconListEntry.type == ST_ROOT) ||
6874 (drop_target_node->ie_IconListEntry.type == ST_USERDIR) ||
6875 (drop_target_node->ie_IconListEntry.type == ST_LINKDIR) ||
6876 (drop_target_node->ie_IconListEntry.type == ST_FILE) ||
6877 (drop_target_node->ie_IconListEntry.type == ST_LINKFILE)))
6879 /* Dropped on some entry */
6880 if ((drop_target_node->ie_IconListEntry.type != ST_ROOT) && (drop_target_node->ie_IconListEntry.type != ST_SOFTLINK))
6882 if (directory_path)
6884 int fulllen = strlen(directory_path) + strlen(drop_target_node->ie_IconListEntry.label) + 2;
6886 if ((dragDropEvent->drop_TargetPath = AllocVec(fulllen, MEMF_CLEAR)) == NULL)
6888 bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__);
6889 goto dragdropdone;
6891 strcpy(dragDropEvent->drop_TargetPath, directory_path);
6892 AddPart(dragDropEvent->drop_TargetPath, drop_target_node->ie_IconListEntry.label, fulllen);
6894 else
6895 goto dragdropdone;
6897 else
6899 if ((dragDropEvent->drop_TargetPath = AllocVec(strlen(drop_target_node->ie_IconListEntry.label) + 1, MEMF_CLEAR)) == NULL)
6901 bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__);
6902 goto dragdropdone;
6904 strcpy(dragDropEvent->drop_TargetPath, drop_target_node->ie_IconListEntry.label);
6907 #if defined(DEBUG_ILC_ICONDRAGDROP)
6908 D(bug("[IconList] %s: Target Entry Full Path = '%s'\n", __PRETTY_FUNCTION__, dragDropEvent->drop_TargetPath));
6909 #endif
6910 /* mark the Entry the selection was dropped on*/
6911 //drop_target_node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6912 //data->icld_UpdateMode = UPDATE_SINGLEENTRY;
6913 //data->update_entry = drop_target_node;
6914 //MUI_Redraw(obj,MADF_DRAWUPDATE);
6916 else
6918 /* Not dropped on entry -> get path of DESTINATION iconlist */
6919 /* Note: directory_path is NULL when dropped on Wanderer's desktop */
6920 if ((message->obj != obj) && directory_path)
6922 #if defined(DEBUG_ILC_ICONDRAGDROP)
6923 D(bug("[IconList] %s: drop entry: Icons dropped in window '%s'\n", __PRETTY_FUNCTION__, directory_path));
6924 #endif
6925 /* copy path */
6926 if ((dragDropEvent->drop_TargetPath = AllocVec(strlen(directory_path) + 1, MEMF_CLEAR)) != NULL)
6928 strcpy(dragDropEvent->drop_TargetPath, directory_path);
6930 else
6932 #if defined(DEBUG_ILC_ICONDRAGDROP)
6933 D(bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__));
6934 #endif
6935 goto dragdropdone;
6938 else if (message->obj == obj)
6940 #if defined(DEBUG_ILC_ICONDRAGDROP)
6941 D(bug("[IconList] %s: drop entry: Entry Move detected ..\n", __PRETTY_FUNCTION__));
6942 #endif
6943 iconMove = TRUE;
6945 /* Adjust entry posiions .. */
6946 #if defined(DEBUG_ILC_ICONDRAGDROP)
6947 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));
6948 #endif
6949 LONG offset_x = message->x - (data->click_x + _mleft(obj));
6950 LONG offset_y = message->y - (data->click_y + _mtop(obj));
6952 entry = (IPTR)MUIV_IconList_NextIcon_Start;
6953 while ((IPTR)entry != MUIV_IconList_NextIcon_End)
6955 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
6957 if ((IPTR)entry != MUIV_IconList_NextIcon_End)
6959 entry->ile_IconEntry->ie_IconX += offset_x;
6960 entry->ile_IconEntry->ie_IconY += offset_y;
6961 /* Remember new position as provided */
6962 DoMethod(obj, MUIM_IconList_PropagateEntryPos, entry->ile_IconEntry);
6964 SET(obj, MUIA_IconList_IconMoved, (IPTR)entry); // Now notify
6966 MUI_Redraw(obj,MADF_DRAWOBJECT);
6967 DoMethod(obj, MUIM_IconList_CoordsSort);
6969 else
6971 #if defined(DEBUG_ILC_ICONDRAGDROP)
6972 D(bug("[IconList] %s: Icons Dropped on Wanderer Desktop (unhandled)!\n", __PRETTY_FUNCTION__));
6973 #endif
6974 iconMove = TRUE;
6979 if (!(iconMove))
6981 int copycount = 0;
6982 /* Create list of entries to copy .. */
6983 entry = (IPTR)MUIV_IconList_NextIcon_Start;
6984 while ((IPTR)entry != MUIV_IconList_NextIcon_End)
6986 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
6988 if ((IPTR)entry != MUIV_IconList_NextIcon_End)
6990 struct IconList_Drop_SourceEntry *sourceEntry = NULL;
6991 sourceEntry = AllocMem(sizeof(struct IconList_Drop_SourceEntry), MEMF_CLEAR);
6992 if ((entry->type != ST_ROOT) && (entry->type != ST_SOFTLINK))
6994 int fulllen = 0;
6995 char *path = NULL;
6997 GET(message->obj, MUIA_IconDrawerList_Drawer, &path);
6998 /* Properly expand the location incase it uses devices rather than volumes */
6999 if (path != NULL)
7001 tmp_dirlock = Lock(path, SHARED_LOCK);
7002 if (tmp_dirlock)
7004 if (NameFromLock(tmp_dirlock, tmp_dirbuff, 256))
7006 path = tmp_dirbuff;
7008 UnLock(tmp_dirlock);
7011 if (strcasecmp(dragDropEvent->drop_TargetPath, path) != 0)
7013 fulllen = strlen(path) + strlen(entry->ile_IconEntry->ie_IconNode.ln_Name) + 2;
7014 sourceEntry->dropse_Node.ln_Name = AllocVec(fulllen, MEMF_CLEAR);
7015 strcpy(sourceEntry->dropse_Node.ln_Name, path);
7016 AddPart(sourceEntry->dropse_Node.ln_Name, entry->label, fulllen);
7017 #if defined(DEBUG_ILC_ICONDRAGDROP)
7018 D(bug("[IconList] %s: Source Entry (Full Path) = '%s'\n", __PRETTY_FUNCTION__, sourceEntry->dropse_Node.ln_Name));
7019 #endif
7023 else
7025 sourceEntry->dropse_Node.ln_Name = AllocVec(strlen(entry->label) + 1, MEMF_CLEAR);
7026 strcpy(sourceEntry->dropse_Node.ln_Name, entry->label);
7027 #if defined(DEBUG_ILC_ICONDRAGDROP)
7028 D(bug("[IconList] %s: Source Entry = '%s'\n", __PRETTY_FUNCTION__, sourceEntry->dropse_Node.ln_Name));
7029 #endif
7032 if ((sourceEntry->dropse_Node.ln_Name != NULL) && (strcasecmp(dragDropEvent->drop_TargetPath, sourceEntry->dropse_Node.ln_Name) != 0))
7034 copycount += 1;
7035 AddTail(&dragDropEvent->drop_SourceList, &sourceEntry->dropse_Node);
7037 else
7039 #if defined(DEBUG_ILC_ICONDRAGDROP)
7040 D(bug("[IconList] %s: Source == Dest, Skipping!\n", __PRETTY_FUNCTION__));
7041 #endif
7042 if ( sourceEntry->dropse_Node.ln_Name) FreeVec(sourceEntry->dropse_Node.ln_Name);
7043 FreeMem(sourceEntry, sizeof(struct IconList_Drop_SourceEntry));
7047 if (copycount > 0)
7049 dragDropEvent->drop_TargetObj = obj;
7051 #if defined(DEBUG_ILC_ICONDRAGDROP)
7052 D(bug("[IconList] %s: Causing DROP notification..\n", __PRETTY_FUNCTION__));
7053 #endif
7054 SET(obj, MUIA_IconList_IconsDropped, (IPTR)dragDropEvent);
7055 DoMethod(obj, MUIM_IconList_CoordsSort);
7057 else
7059 if (dragDropEvent->drop_TargetPath) FreeVec(dragDropEvent->drop_TargetPath);
7060 FreeMem(dragDropEvent, sizeof(struct IconList_Drop_Event));
7064 else
7066 #if defined(DEBUG_ILC_ICONDRAGDROP)
7067 D(bug("[IconList] %s: BUG - DragDrop received with no source icons!\n", __PRETTY_FUNCTION__));
7068 #endif
7069 NNSET(obj, MUIA_IconList_IconsDropped, (IPTR)NULL);
7072 dragdropdone:
7073 return DoSuperMethodA(CLASS, obj, (Msg)message);
7077 ///MUIM_UnselectAll()
7078 /**************************************************************************
7079 MUIM_UnselectAll
7080 **************************************************************************/
7081 IPTR IconList__MUIM_IconList_UnselectAll(struct IClass *CLASS, Object *obj, Msg message)
7083 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7084 struct Node *node = NULL, *next_node = NULL;
7085 BOOL changed = FALSE;
7087 #if defined(DEBUG_ILC_FUNCS)
7088 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7089 #endif
7091 data->icld_SelectionLastClicked = NULL;
7092 data->icld_FocusIcon = NULL;
7093 #if defined(__AROS__)
7094 ForeachNodeSafe(&data->icld_SelectionList, node, next_node)
7095 #else
7096 Foreach_NodeSafe(&data->icld_SelectionList, node, next_node);
7097 #endif
7099 struct IconEntry *entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
7100 BOOL update_entry = FALSE;
7102 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7104 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
7106 Remove(node);
7107 entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
7108 update_entry = TRUE;
7110 if (entry->ie_Flags & ICONENTRY_FLAG_FOCUS)
7112 entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
7113 update_entry = TRUE;
7117 if (update_entry)
7119 changed = TRUE;
7120 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
7121 data->update_entry = entry;
7122 MUI_Redraw(obj, MADF_DRAWUPDATE);
7126 if (changed)
7127 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
7129 return 1;
7133 ///MUIM_SelectAll()
7134 /**************************************************************************
7135 MUIM_SelectAll
7136 **************************************************************************/
7137 IPTR IconList__MUIM_IconList_SelectAll(struct IClass *CLASS, Object *obj, Msg message)
7139 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7140 struct IconEntry *node = NULL;
7141 BOOL changed = FALSE;
7143 #if defined(DEBUG_ILC_FUNCS)
7144 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7145 #endif
7147 node = (struct IconEntry *)GetHead(&data->icld_IconList);
7149 while (node != NULL)
7151 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7153 BOOL update_entry = FALSE;
7155 if (!(node->ie_Flags & ICONENTRY_FLAG_SELECTED))
7157 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
7158 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
7159 update_entry = TRUE;
7161 data->icld_SelectionLastClicked = node;
7163 else if (node->ie_Flags & ICONENTRY_FLAG_FOCUS)
7165 node->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
7166 update_entry = TRUE;
7169 if (update_entry)
7171 changed = TRUE;
7172 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
7173 data->update_entry = node;
7174 MUI_Redraw(obj, MADF_DRAWUPDATE);
7177 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
7180 if ((data->icld_SelectionLastClicked) && (data->icld_SelectionLastClicked != data->icld_FocusIcon))
7182 data->icld_FocusIcon = data->icld_SelectionLastClicked;
7183 if (!(data->icld_FocusIcon->ie_Flags & ICONENTRY_FLAG_FOCUS))
7185 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
7186 data->icld_FocusIcon->ie_Flags |= ICONENTRY_FLAG_FOCUS;
7187 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
7188 data->update_entry = data->icld_FocusIcon;
7189 MUI_Redraw(obj, MADF_DRAWUPDATE);
7193 if (changed)
7194 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
7196 return 1;
7200 ///IconList__MUIM_IconList_CoordsSort()
7201 IPTR IconList__MUIM_IconList_CoordsSort(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Sort *message)
7203 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7205 struct IconEntry *entry = NULL,
7206 *test_icon = NULL;
7208 struct List list_VisibleIcons;
7209 struct List list_HiddenIcons;
7210 // struct List list_UnplacedIcons;
7213 perform a quick sort of the iconlist based on entry coords
7214 this method DOESNT cause any visual output.
7216 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONSORTING)
7217 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7218 #endif
7220 NewList((struct List*)&list_VisibleIcons);
7221 NewList((struct List*)&list_HiddenIcons);
7223 /*move list into our local list struct(s)*/
7224 while ((entry = (struct IconEntry *)RemTail((struct List*)&data->icld_IconList)))
7226 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7228 AddHead((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
7230 else
7231 AddHead((struct List*)&list_HiddenIcons, (struct Node *)&entry->ie_IconNode);
7234 while ((entry = (struct IconEntry *)RemTail((struct List*)&list_VisibleIcons)))
7236 if ((test_icon = (struct IconEntry *)GetTail(&data->icld_IconList)) != NULL)
7238 while (test_icon != NULL)
7240 if (((data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconX > entry->ie_IconX)) ||
7241 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconY > entry->ie_IconY)))
7243 test_icon = (struct IconEntry *)GetPred(&test_icon->ie_IconNode);
7244 continue;
7246 else break;
7249 while (test_icon != NULL)
7251 if (((data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconY > entry->ie_IconY)) ||
7252 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconX > entry->ie_IconX)))
7254 test_icon = (struct IconEntry *)GetPred(&test_icon->ie_IconNode);
7255 continue;
7257 else break;
7259 Insert((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode, (struct Node *)&test_icon->ie_IconNode);
7261 else
7262 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7264 #if defined(DEBUG_ILC_ICONSORTING)
7265 D(bug("[IconList] %s: Done\n", __PRETTY_FUNCTION__));
7266 #endif
7268 while ((entry = (struct IconEntry *)RemTail((struct List*)&list_HiddenIcons)))
7270 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7273 #if defined(DEBUG_ILC_ICONSORTING_DUMP)
7274 #if defined(__AROS__)
7275 ForeachNode(&data->icld_IconList, entry)
7276 #else
7277 Foreach_Node(&data->icld_IconList, entry);
7278 #endif
7280 D(bug("[IconList] %s: %d %d '%s'\n", __PRETTY_FUNCTION__, entry->ie_IconX, entry->ie_IconY, entry->ie_IconListEntry.label));
7282 #endif
7284 return TRUE;
7288 ///MUIM_Sort()
7289 /**************************************************************************
7290 MUIM_Sort - sortsort
7291 **************************************************************************/
7292 IPTR IconList__MUIM_IconList_Sort(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Sort *message)
7294 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7295 struct IconEntry *entry = NULL,
7296 *icon1 = NULL,
7297 *icon2 = NULL;
7299 struct List list_VisibleIcons,
7300 list_SortedIcons,
7301 list_HiddenIcons;
7303 BOOL sortme, reversable = TRUE, enqueue = FALSE;
7304 int i, visible_count = 0;
7306 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONSORTING)
7307 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7308 #endif
7310 /* Reset incase view options have changed .. */
7311 data->icld_IconAreaLargestWidth = 0;
7312 data->icld_IconAreaLargestHeight = 0;
7313 data->icld_IconLargestHeight = 0;
7314 data->icld_LabelLargestHeight = 0;
7316 #if defined(DEBUG_ILC_ICONSORTING)
7317 D(bug("[IconList] %s: Sort-Flags : %x\n", __PRETTY_FUNCTION__, (data->icld_SortFlags & MUIV_IconList_Sort_MASK)));
7318 #endif
7319 NewList((struct List*)&list_VisibleIcons);
7320 NewList((struct List*)&list_SortedIcons);
7321 NewList((struct List*)&list_HiddenIcons);
7323 /*move list into our local list struct(s)*/
7324 while ((entry = (struct IconEntry *)RemTail((struct List*)&data->icld_IconList)))
7326 if (!(entry->ie_Flags & ICONENTRY_FLAG_HASICON))
7328 if (data->icld_DisplayFlags & ICONLIST_DISP_SHOWINFO)
7330 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7332 entry->ie_Flags &= ~(ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
7335 else if (!(entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
7337 entry->ie_Flags |= (ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
7340 else
7342 if (!(entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
7344 entry->ie_Flags |= (ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
7348 /* Now we have fixed visibility lets dump them into the correct list for sorting */
7349 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
7351 if(entry->ie_AreaWidth > data->icld_IconAreaLargestWidth) data->icld_IconAreaLargestWidth = entry->ie_AreaWidth;
7352 if(entry->ie_AreaHeight > data->icld_IconAreaLargestHeight) data->icld_IconAreaLargestHeight = entry->ie_AreaHeight;
7353 if(entry->ie_IconHeight > data->icld_IconLargestHeight) data->icld_IconLargestHeight = entry->ie_IconHeight;
7354 if((entry->ie_AreaHeight - entry->ie_IconHeight) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = entry->ie_AreaHeight - entry->ie_IconHeight;
7356 if (((data->icld_SortFlags & MUIV_IconList_Sort_AutoSort) == 0) && (entry->ie_ProvidedIconX == NO_ICON_POSITION))
7357 AddTail((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
7358 else
7359 AddHead((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
7360 visible_count++;
7362 else
7364 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
7366 Remove(&entry->ie_SelectionNode);
7368 entry->ie_Flags &= ~(ICONENTRY_FLAG_SELECTED|ICONENTRY_FLAG_FOCUS);
7369 if (data->icld_SelectionLastClicked == entry) data->icld_SelectionLastClicked = NULL;
7370 if (data->icld_FocusIcon == entry) data->icld_FocusIcon = data->icld_SelectionLastClicked;
7371 AddHead((struct List*)&list_HiddenIcons, (struct Node *)&entry->ie_IconNode);
7375 /* Copy each visible entry back to the main list, sorting as we go*/
7376 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_VisibleIcons)))
7378 icon1 = (struct IconEntry *)GetHead(&list_SortedIcons);
7379 icon2 = NULL;
7381 sortme = FALSE;
7383 if (visible_count > 1)
7385 #if defined(DEBUG_ILC_ICONSORTING)
7386 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));
7387 #endif
7388 while (icon1)
7390 if(((icon1->ie_IconListEntry.type == ST_ROOT) || (icon1->ie_IconListEntry.type == ST_LINKDIR) || (icon1->ie_IconListEntry.type == ST_LINKFILE))
7391 || (data->icld_SortFlags & MUIV_IconList_Sort_DrawersMixed))
7393 /*volume list or drawers mixed*/
7394 sortme = TRUE;
7396 else
7398 /*drawers first*/
7399 if ((icon1->ie_IconListEntry.type == ST_USERDIR) && (entry->ie_IconListEntry.type == ST_USERDIR))
7401 sortme = TRUE;
7403 else
7405 if ((icon1->ie_IconListEntry.type != ST_USERDIR) && (entry->ie_IconListEntry.type != ST_USERDIR))
7406 sortme = TRUE;
7407 else
7409 /* we are the first drawer to arrive or we need to insert ourselves
7410 due to being sorted to the end of the drawers*/
7412 if ((!icon2 || icon2->ie_IconListEntry.type == ST_USERDIR) &&
7413 (entry->ie_IconListEntry.type == ST_USERDIR) &&
7414 (icon1->ie_IconListEntry.type != ST_USERDIR))
7416 #if defined(DEBUG_ILC_ICONSORTING)
7417 D(bug("[IconList] %s: force %s\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label));
7418 #endif
7419 break;
7425 if (sortme)
7427 i = 0;
7429 if ((data->icld_SortFlags & MUIV_IconList_Sort_AutoSort) == 0)
7431 if ((entry->ie_ProvidedIconX != NO_ICON_POSITION) && (entry->ie_ProvidedIconY != NO_ICON_POSITION))
7433 i = 1;
7437 if (i == 0)
7439 if (data->icld_SortFlags & MUIV_IconList_Sort_ByDate)
7441 /* Sort by Date */
7442 i = CompareDates((const struct DateStamp *)&entry->ie_FileInfoBlock->fib_Date,(const struct DateStamp *)&icon1->ie_FileInfoBlock->fib_Date);
7444 else if (data->icld_SortFlags & MUIV_IconList_Sort_BySize)
7446 /* Sort by Size .. */
7447 i = entry->ie_FileInfoBlock->fib_Size - icon1->ie_FileInfoBlock->fib_Size;
7449 else if ((data->icld_SortFlags & MUIV_IconList_Sort_ByType) && ((entry->ie_IconListEntry.type == ST_FILE) || (entry->ie_IconListEntry.type == ST_USERDIR)))
7451 /* Sort by Type .. */
7452 /* TODO: Sort icons based on type using datatypes */
7454 else
7456 /* Sort by Name .. */
7457 i = Stricmp(entry->ie_IconListEntry.label, icon1->ie_IconListEntry.label);
7458 if ((data->icld_SortFlags & MUIV_IconList_Sort_DrawersMixed) == 0) enqueue = TRUE;
7462 if ((reversable) && data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
7464 if (i > 0)
7465 break;
7467 else if (i < 0)
7468 break;
7470 icon2 = icon1;
7471 icon1 = (struct IconEntry *)GetSucc(&icon1->ie_IconNode);
7474 Insert((struct List*)&list_SortedIcons, (struct Node *)&entry->ie_IconNode, (struct Node *)&icon2->ie_IconNode);
7476 if (enqueue)
7478 /* Quickly resort based on node priorities .. */
7479 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_SortedIcons)))
7481 Enqueue((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7484 else
7486 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_SortedIcons)))
7488 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7492 DoMethod(obj, MUIM_IconList_PositionIcons);
7493 MUI_Redraw(obj, MADF_DRAWOBJECT);
7495 if ((data->icld_SortFlags & MUIV_IconList_Sort_Orders) != 0)
7497 DoMethod(obj, MUIM_IconList_CoordsSort);
7499 /* leave hidden icons on a seperate list to speed up normal list parsing ? */
7500 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_HiddenIcons)))
7502 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7505 SET(obj, MUIA_IconList_Changed, TRUE);
7507 return 1;
7511 ///MUIM_DragReport()
7512 /**************************************************************************
7513 MUIM_DragReport. Since MUI doesn't change the drop object if the dragged
7514 object is moved above another window (while still in the bounds of the
7515 orginal drop object) we must do it here manually to be compatible with
7516 MUI. Maybe Zune should fix this bug somewhen.
7517 **************************************************************************/
7518 IPTR IconList__MUIM_DragReport(struct IClass *CLASS, Object *obj, struct MUIP_DragReport *message)
7520 struct Window *wnd = _window(obj);
7521 struct Layer *l = NULL;
7523 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
7524 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7525 #endif
7527 l = WhichLayer(&wnd->WScreen->LayerInfo, wnd->LeftEdge + message->x, wnd->TopEdge + message->y);
7529 if (l != wnd->WLayer) return MUIV_DragReport_Abort;
7531 return MUIV_DragReport_Continue;
7535 ///MUIM_IconList_UnknownDropDestination()
7536 /**************************************************************************
7537 MUIM_IconList_UnknownDropDestination
7538 **************************************************************************/
7539 IPTR IconList__MUIM_UnknownDropDestination(struct IClass *CLASS, Object *obj, struct MUIP_UnknownDropDestination *message)
7541 #if defined(DEBUG_ILC_FUNCS) || defined(DEBUG_ILC_ICONDRAGDROP)
7542 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7543 #endif
7544 #if defined(DEBUG_ILC_ICONDRAGDROP)
7545 D(bug("[IconList] %s: icons dropped on custom window \n", __PRETTY_FUNCTION__));
7546 #endif
7548 SET(obj, MUIA_IconList_AppWindowDrop, (IPTR)message); /* Now notify */
7550 return (IPTR)NULL;
7554 ///MUIM_IconList_MakeEntryVisible()
7555 /**************************************************************************
7556 Move the visible area so that the selected entry becomes visible ..
7557 **************************************************************************/
7558 IPTR IconList__MUIM_IconList_MakeEntryVisible(struct IClass *CLASS, Object *obj, struct MUIP_IconList_MakeEntryVisible *message)
7560 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7561 BOOL viewmoved = FALSE;
7562 struct Rectangle iconrect, viewrect;
7564 #if defined(DEBUG_ILC_FUNCS)
7565 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7566 #endif
7568 viewrect.MinX = data->icld_ViewX;
7569 viewrect.MaxX = data->icld_ViewX + data->icld_AreaWidth;
7570 viewrect.MinY = data->icld_ViewY;
7571 viewrect.MaxY = data->icld_ViewY + data->icld_AreaHeight;
7573 IconList_GetIconAreaRectangle(obj, data, message->entry, &iconrect);
7575 if (!(RectAndRect(&viewrect, &iconrect)))
7577 viewmoved = TRUE;
7578 if (message->entry->ie_IconX < data->icld_ViewX)
7579 data->icld_ViewX = message->entry->ie_IconX;
7580 else if (message->entry->ie_IconX > (data->icld_ViewX + data->icld_AreaWidth))
7581 data->icld_ViewX = (message->entry->ie_IconX + message->entry->ie_AreaWidth) - data->icld_AreaWidth;
7583 if (message->entry->ie_IconY < data->icld_ViewY)
7584 data->icld_ViewY = message->entry->ie_IconX;
7585 else if (message->entry->ie_IconY > (data->icld_ViewY + data->icld_AreaHeight))
7586 data->icld_ViewY = (message->entry->ie_IconY + message->entry->ie_AreaHeight) - data->icld_AreaHeight;
7589 if (viewmoved)
7591 #if defined(DEBUG_ILC_ICONRENDERING)
7592 D(bug("[IconList]: %s: call SetSuperAttrs()\n", __PRETTY_FUNCTION__));
7593 #endif
7594 SetSuperAttrs(CLASS, obj, MUIA_Virtgroup_Left, data->icld_ViewX,
7595 MUIA_Virtgroup_Top, data->icld_ViewY,
7596 TAG_DONE);
7598 #if defined(DEBUG_ILC_ICONRENDERING)
7599 D(bug("[IconList]: %s: call SetAttrs()\n", __PRETTY_FUNCTION__));
7600 #endif
7601 SetAttrs(obj, MUIA_Virtgroup_Left, data->icld_ViewX,
7602 MUIA_Virtgroup_Top, data->icld_ViewY,
7603 TAG_DONE);
7605 #if defined(DEBUG_ILC_ICONRENDERING)
7606 D(bug("[IconList]: %s: call MUI_Redraw()\n", __PRETTY_FUNCTION__));
7607 #endif
7608 MUI_Redraw(obj,MADF_DRAWOBJECT);
7610 return 1;
7613 #if defined(WANDERER_BUILTIN_ICONLIST)
7614 BOOPSI_DISPATCHER(IPTR,IconList_Dispatcher, CLASS, obj, message)
7616 #if defined(__AROS__)
7617 switch (message->MethodID)
7618 #else
7619 struct IClass *CLASS = cl;
7620 Msg message = msg;
7622 switch (msg->MethodID)
7623 #endif
7625 case OM_NEW: return IconList__OM_NEW(CLASS, obj, (struct opSet *)message);
7626 case OM_DISPOSE: return IconList__OM_DISPOSE(CLASS, obj, message);
7627 case OM_SET: return IconList__OM_SET(CLASS, obj, (struct opSet *)message);
7628 case OM_GET: return IconList__OM_GET(CLASS, obj, (struct opGet *)message);
7629 case OM_ADDMEMBER:
7630 case MUIM_Family_AddTail: return IconList__MUIM_Family_AddTail(CLASS, obj, (APTR)message);
7631 case MUIM_Family_AddHead: return IconList__MUIM_Family_AddHead(CLASS, obj, (APTR)message);
7632 case OM_REMMEMBER:
7633 case MUIM_Family_Remove: return IconList__MUIM_Family_Remove(CLASS, obj, (APTR)message);
7635 case MUIM_Setup: return IconList__MUIM_Setup(CLASS, obj, (struct MUIP_Setup *)message);
7637 case MUIM_Show: return IconList__MUIM_Show(CLASS,obj, (struct MUIP_Show *)message);
7638 case MUIM_Hide: return IconList__MUIM_Hide(CLASS,obj, (struct MUIP_Hide *)message);
7639 case MUIM_Cleanup: return IconList__MUIM_Cleanup(CLASS, obj, (struct MUIP_Cleanup *)message);
7640 case MUIM_AskMinMax: return IconList__MUIM_AskMinMax(CLASS, obj, (struct MUIP_AskMinMax *)message);
7641 case MUIM_Draw: return IconList__MUIM_Draw(CLASS, obj, (struct MUIP_Draw *)message);
7642 #if defined(__AROS__)
7643 case MUIM_Layout: return IconList__MUIM_Layout(CLASS, obj, (struct MUIP_Layout *)message);
7644 #endif
7645 case MUIM_HandleEvent: return IconList__MUIM_HandleEvent(CLASS, obj, (struct MUIP_HandleEvent *)message);
7646 case MUIM_CreateDragImage: return IconList__MUIM_CreateDragImage(CLASS, obj, (APTR)message);
7647 case MUIM_DeleteDragImage: return IconList__MUIM_DeleteDragImage(CLASS, obj, (APTR)message);
7648 case MUIM_DragQuery: return IconList__MUIM_DragQuery(CLASS, obj, (APTR)message);
7649 case MUIM_DragReport: return IconList__MUIM_DragReport(CLASS, obj, (APTR)message);
7650 case MUIM_DragDrop: return IconList__MUIM_DragDrop(CLASS, obj, (APTR)message);
7651 #if defined(__AROS__)
7652 case MUIM_UnknownDropDestination: return IconList__MUIM_UnknownDropDestination(CLASS, obj, (APTR)message);
7653 #endif
7654 case MUIM_IconList_Update: return IconList__MUIM_IconList_Update(CLASS, obj, (APTR)message);
7655 case MUIM_IconList_Clear: return IconList__MUIM_IconList_Clear(CLASS, obj, (APTR)message);
7656 case MUIM_IconList_RethinkDimensions: return IconList__MUIM_IconList_RethinkDimensions(CLASS, obj, (APTR)message);
7657 case MUIM_IconList_CreateEntry: return IconList__MUIM_IconList_CreateEntry(CLASS, obj, (APTR)message);
7658 case MUIM_IconList_UpdateEntry: return IconList__MUIM_IconList_UpdateEntry(CLASS, obj, (APTR)message);
7659 case MUIM_IconList_DestroyEntry: return IconList__MUIM_IconList_DestroyEntry(CLASS, obj, (APTR)message);
7660 case MUIM_IconList_DrawEntry: return IconList__MUIM_IconList_DrawEntry(CLASS, obj, (APTR)message);
7661 case MUIM_IconList_DrawEntryLabel: return IconList__MUIM_IconList_DrawEntryLabel(CLASS, obj, (APTR)message);
7662 case MUIM_IconList_NextIcon: return IconList__MUIM_IconList_NextIcon(CLASS, obj, (APTR)message);
7663 case MUIM_IconList_GetIconPrivate: return IconList__MUIM_IconList_GetIconPrivate(CLASS, obj, (APTR)message);
7664 case MUIM_IconList_UnselectAll: return IconList__MUIM_IconList_UnselectAll(CLASS, obj, (APTR)message);
7665 case MUIM_IconList_Sort: return IconList__MUIM_IconList_Sort(CLASS, obj, (APTR)message);
7666 case MUIM_IconList_CoordsSort: return IconList__MUIM_IconList_CoordsSort(CLASS, obj, (APTR)message);
7667 case MUIM_IconList_PositionIcons: return IconList__MUIM_IconList_PositionIcons(CLASS, obj, (APTR)message);
7668 case MUIM_IconList_SelectAll: return IconList__MUIM_IconList_SelectAll(CLASS, obj, (APTR)message);
7669 case MUIM_IconList_MakeEntryVisible: return IconList__MUIM_IconList_MakeEntryVisible(CLASS, obj, (APTR)message);
7672 return DoSuperMethodA(CLASS, obj, message);
7674 BOOPSI_DISPATCHER_END
7676 #if defined(__AROS__)
7677 /* Class descriptor. */
7678 const struct __MUIBuiltinClass _MUI_IconList_desc = {
7679 MUIC_IconList,
7680 MUIC_Area,
7681 sizeof(struct IconList_DATA),
7682 (void*)IconList_Dispatcher
7684 #endif
7685 #endif /* WANDERER_BUILTIN_ICONLIST */
7687 #if !defined(__AROS__)
7688 struct MUI_CustomClass *initIconListClass(void)
7690 return (struct MUI_CustomClass *) MUI_CreateCustomClass(NULL, MUIC_Area, NULL, sizeof(struct IconList_DATA), ENTRY(IconList_Dispatcher));
7692 #endif