Fix lasso row selection when scrolled down in list view-mode
[AROS.git] / workbench / system / Wanderer / Classes / iconlist.c
blob6f825ebf55166faa4177ddf40f405d1e376804a6
1 /*
2 Copyright 2002-2010, 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 static struct TagItem __iconList_BackBuffLayerTags[] =
124 { LA_Visible, FALSE },
125 { TAG_DONE, }
128 #ifndef NO_ICON_POSITION
129 #define NO_ICON_POSITION (0x8000000) /* belongs to workbench/workbench.h */
130 #endif
132 #define UPDATE_HEADERENTRY 1
133 #define UPDATE_SINGLEENTRY 2
134 #define UPDATE_SCROLL 3
135 #define UPDATE_RESIZE 4
137 #define LEFT_BUTTON 1
138 #define RIGHT_BUTTON 2
139 #define MIDDLE_BUTTON 4
141 #define ICONLIST_DRAWMODE_NORMAL 1
142 #define ICONLIST_DRAWMODE_FAST 2
144 /* Values used for List View-Mode */
145 #define COLOR_COLUMN_BACKGROUND 0
146 #define COLOR_COLUMN_BACKGROUND_SORTED 1
147 #define COLOR_COLUMN_BACKGROUND_LASSO 2
148 #define COLOR_COLUMN_BACKGROUND_LASSO_SORTED 3
150 #define COLOR_SELECTED_BACKGROUND 4
151 #define COLOR_SELECTED_BACKGROUND_SORTED 5
153 #define MIN_COLUMN_WIDTH 10
155 #define COLUMN_ALIGN_LEFT 0
156 #define COLUMN_ALIGN_CENTER 1
157 #define COLUMN_ALIGN_RIGHT 2
159 #define LINE_SPACING_TOP 2
160 #define LINE_SPACING_BOTTOM 2
161 #define LINE_EXTRAHEIGHT (LINE_SPACING_TOP + LINE_SPACING_BOTTOM)
163 #define LINE_SPACING_LEFT 1
164 #define LINE_SPACING_RIGHT 1
165 #define LINE_EXTRAWIDTH (LINE_SPACING_LEFT + LINE_SPACING_RIGHT)
167 #define ENTRY_SPACING_LEFT 1
168 #define ENTRY_SPACING_RIGHT 1
169 #define ENTRY_EXTRAWIDTH (ENTRY_SPACING_LEFT + ENTRY_SPACING_RIGHT)
171 #define HEADERLINE_SPACING_TOP 3
172 #define HEADERLINE_SPACING_BOTTOM 3
173 #define HEADERLINE_EXTRAHEIGHT (HEADERLINE_SPACING_TOP + HEADERLINE_SPACING_BOTTOM)
175 #define HEADERLINE_SPACING_LEFT 1
176 #define HEADERLINE_SPACING_RIGHT 1
177 #define HEADERLINE_EXTRAWIDTH (HEADERLINE_SPACING_LEFT + HEADERLINE_SPACING_RIGHT)
179 #define HEADERENTRY_SPACING_LEFT 4
180 #define HEADERENTRY_SPACING_RIGHT 4
181 #define HEADERENTRY_EXTRAWIDTH (HEADERENTRY_SPACING_LEFT + HEADERENTRY_SPACING_RIGHT)
183 enum
185 INDEX_NAME,
186 INDEX_SIZE,
187 INDEX_PROTECTION,
188 INDEX_DATE,
189 INDEX_TIME,
190 INDEX_COMMENT
193 /**************************************************************************
194 Support Functions
195 **************************************************************************/
197 #define ForeachPrevNode(list, node) \
198 for \
200 node = (void *)(((struct List *)(list))->lh_TailPred); \
201 ((struct Node *)(node))->ln_Pred; \
202 node = (void *)(((struct Node *)(node))->ln_Pred) \
205 #define RPALPHAFLAT (1 << 0)
206 #define RPALPHARADIAL (1 << 1)
208 static void RastPortSetAlpha(struct RastPort *arport, ULONG ax, ULONG ay, ULONG width, ULONG height, UBYTE val, UBYTE alphamode)
210 ULONG x, y;
211 ULONG alphaval, pixelval;
213 for (y = 0; y < height; y++)
215 for (x = 0; x < width; x++)
217 if ((pixelval = ReadRGBPixel(arport, x, y)))
219 if (alphamode == RPALPHARADIAL){
220 //Set the alpha value based on distance from ax,ay
221 } else {
222 alphaval = val;
224 WriteRGBPixel(arport, x, y, ((pixelval & 0xffffff)|(alphaval << 24)));
230 ///RectAndRect()
231 // Entry/Label Area support functions
232 static int RectAndRect(struct Rectangle *a, struct Rectangle *b)
234 if ((a->MinX > b->MaxX) || (a->MinY > b->MaxY) || (a->MaxX < b->MinX) || (a->MaxY < b->MinY))
235 return 0;
236 return 1;
240 ///Node_NextVisible()
241 // IconEntry List navigation functions ..
242 static struct IconEntry *Node_NextVisible(struct IconEntry *current_Node)
244 current_Node = (struct IconEntry *)GetSucc(&current_Node->ie_IconNode);
245 while ((current_Node != NULL) && (!(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
247 current_Node = (struct IconEntry *)GetSucc(&current_Node->ie_IconNode);
249 return current_Node;
253 ///Node_FirstVisible()
254 static struct IconEntry *Node_FirstVisible(struct List *icon_list)
256 struct IconEntry *current_Node = (struct IconEntry *)GetHead(icon_list);
258 if ((current_Node != NULL) && !(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE))
259 current_Node = Node_NextVisible(current_Node);
261 return current_Node;
265 ///Node_PreviousVisible()
266 static struct IconEntry *Node_PreviousVisible(struct IconEntry *current_Node)
268 current_Node = (struct IconEntry *)GetPred(&current_Node->ie_IconNode);
269 while ((current_Node != NULL) && (!(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
271 current_Node = (struct IconEntry *)GetPred(&current_Node->ie_IconNode);
273 return current_Node;
277 ///Node_LastVisible()
278 static struct IconEntry *Node_LastVisible(struct List *icon_list)
280 struct IconEntry *current_Node = (struct IconEntry *)GetTail(icon_list);
282 if ((current_Node != NULL) && !(current_Node->ie_Flags & ICONENTRY_FLAG_VISIBLE))
283 current_Node = Node_PreviousVisible(current_Node);
285 return current_Node;
289 const UBYTE MSG_MEM_G[] = "GB";
290 const UBYTE MSG_MEM_M[] = "MB";
291 const UBYTE MSG_MEM_K[] = "KB";
292 const UBYTE MSG_MEM_B[] = "Bytes";
294 ///FmtSizeToString()
295 static void FmtSizeToString(UBYTE *buf, ULONG num)
297 UQUAD d;
298 UBYTE *ch;
299 struct
301 IPTR val;
302 IPTR dec;
303 } array =
305 num,
309 if (num >= 1073741824)
311 //Gigabytes
312 array.val = num >> 30;
313 d = ((UQUAD)num * 10 + 536870912) / 1073741824;
314 array.dec = d % 10;
315 ch = MSG_MEM_G;
317 else if (num >= 1048576)
319 //Megabytes
320 array.val = num >> 20;
321 d = ((UQUAD)num * 10 + 524288) / 1048576;
322 array.dec = d % 10;
323 ch = MSG_MEM_M;
325 else if (num >= 1024)
327 //Kilobytes
328 array.val = num >> 10;
329 d = (num * 10 + 512) / 1024;
330 array.dec = d % 10;
331 ch = MSG_MEM_K;
333 else
335 //Bytes
336 array.val = num;
337 array.dec = 0;
338 d = 0;
339 ch = MSG_MEM_B;
342 if (!array.dec && (d > array.val * 10))
344 array.val++;
347 RawDoFmt(array.dec ? "%lu.%lu" : "%lu", &array, NULL, buf);
349 while (*buf)
351 buf++;
354 sprintf(buf, " %s", ch);
358 ///GetAbsoluteLassoRect()
359 // get positive lasso coords
360 static void GetAbsoluteLassoRect(struct IconList_DATA *data, struct Rectangle *LassoRectangle)
362 WORD minx = data->icld_LassoRectangle.MinX;
363 WORD miny = data->icld_LassoRectangle.MinY;
364 WORD maxx = data->icld_LassoRectangle.MaxX;
365 WORD maxy = data->icld_LassoRectangle.MaxY;
367 #if defined(DEBUG_ILC_LASSO) && defined(DEBUG_ILC_FUNCS)
368 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
369 #endif
371 if (minx > maxx)
373 /* Swap minx, maxx */
374 minx ^= maxx;
375 maxx ^= minx;
376 minx ^= maxx;
379 if (miny > maxy)
381 /* Swap miny, maxy */
382 miny ^= maxy;
383 maxy ^= miny;
384 miny ^= maxy;
387 LassoRectangle->MinX = data->view_rect.MinX - data->icld_ViewX + minx;
388 LassoRectangle->MinY = data->view_rect.MinY - data->icld_ViewY + miny;
389 LassoRectangle->MaxX = data->view_rect.MinX - data->icld_ViewX + maxx;
390 LassoRectangle->MaxY = data->view_rect.MinY - data->icld_ViewY + maxy;
394 ///IconList_InvertPixelRect()
395 static void IconList_InvertPixelRect(struct RastPort *rp, WORD minx, WORD miny, WORD maxx, WORD maxy, struct Rectangle *clip)
397 struct Rectangle r, clipped_r;
399 #if defined(DEBUG_ILC_RENDERING) && defined(DEBUG_ILC_FUNCS)
400 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
401 #endif
403 if (maxx < minx)
405 /* Swap minx, maxx */
406 minx ^= maxx;
407 maxx ^= minx;
408 minx ^= maxx;
411 if (maxy < miny)
413 /* Swap miny, maxy */
414 miny ^= maxy;
415 maxy ^= miny;
416 miny ^= maxy;
419 r.MinX = minx;
420 r.MinY = miny;
421 r.MaxX = maxx;
422 r.MaxY = maxy;
424 if (AndRectRect(&r, clip, &clipped_r))
426 InvertPixelArray(rp, clipped_r.MinX, clipped_r.MinY,
427 clipped_r.MaxX - clipped_r.MinX + 1, clipped_r.MaxY - clipped_r.MinY + 1);
432 ///IconList_InvertLassoOutlines()
433 // Simple lasso drawing by inverting area outlines
434 static void IconList_InvertLassoOutlines(Object *obj, struct IconList_DATA *data, struct Rectangle *rect)
436 struct Rectangle lasso;
437 struct Rectangle clip;
439 #if defined(DEBUG_ILC_LASSO) && defined(DEBUG_ILC_FUNCS)
440 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
441 #endif
443 /* get abolute iconlist coords */
444 lasso.MinX = rect->MinX + _mleft(obj);
445 lasso.MaxX = rect->MaxX + _mleft(obj);
446 lasso.MinY = rect->MinY + _mtop(obj);
447 lasso.MaxY = rect->MaxY + _mtop(obj);
449 clip.MinX = _mleft(obj);
450 clip.MinY = _mtop(obj);
451 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
453 clip.MinY += data->icld_LVMAttribs->lmva_HeaderHeight;
455 clip.MaxX = _mright(obj);
456 clip.MaxY = _mbottom(obj);
458 /* horizontal lasso lines */
459 IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MinY, lasso.MaxX-1, lasso.MinY + 1, &clip);
460 IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MaxY, lasso.MaxX-1, lasso.MaxY + 1, &clip);
462 /* vertical lasso lines */
463 IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MinY, lasso.MinX + 1, lasso.MaxY - 1, &clip);
464 IconList_InvertPixelRect(_rp(obj), lasso.MaxX, lasso.MinY, lasso.MaxX + 1, lasso.MaxY - 1, &clip);
468 ///IconList_GetIconImageRectangle()
469 //We don't use icon.library's label drawing so we do this by hand
470 static void IconList_GetIconImageRectangle(Object *obj, struct IconList_DATA *data, struct IconEntry *entry, struct Rectangle *rect)
472 #if defined(DEBUG_ILC_ICONPOSITIONING) && defined(DEBUG_ILC_FUNCS)
473 D(bug("[IconList]: %s(entry @ %p)\n", __PRETTY_FUNCTION__, entry));
474 #endif
476 /* Get basic width/height */
477 GetIconRectangleA(NULL, entry->ie_DiskObj, NULL, rect, NULL);
478 #if defined(DEBUG_ILC_ICONPOSITIONING)
479 D(bug("[IconList] %s: MinX %d, MinY %d MaxX %d, MaxY %d\n", __PRETTY_FUNCTION__, rect->MinX, rect->MinY, rect->MaxX, rect->MaxY));
480 #endif
481 entry->ie_IconWidth = (rect->MaxX - rect->MinX) + 1;
482 entry->ie_IconHeight = (rect->MaxY - rect->MinY) + 1;
484 if (entry->ie_IconHeight > data->icld_IconLargestHeight)
485 data->icld_IconLargestHeight = entry->ie_IconHeight;
489 ///IconList_GetIconLabelRectangle()
490 static void IconList_GetIconLabelRectangle(Object *obj, struct IconList_DATA *data, struct IconEntry *entry, struct Rectangle *rect)
492 ULONG outline_offset = 0;
493 ULONG textwidth = 0;
495 #if defined(DEBUG_ILC_ICONPOSITIONING) && defined(DEBUG_ILC_FUNCS)
496 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
497 #endif
499 switch ( data->icld__Option_LabelTextMode )
501 case ICON_TEXTMODE_DROPSHADOW:
502 outline_offset = 1;
503 break;
505 case ICON_TEXTMODE_PLAIN:
506 break;
508 default:
509 outline_offset = 2;
510 break;
513 /* Get entry box width including text width */
514 if ((entry->ie_IconListEntry.label != NULL) && (entry->ie_TxtBuf_DisplayedLabel != NULL))
516 ULONG curlabel_TotalLines;
517 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
519 rect->MinX = 0;
520 rect->MaxX = (((data->icld__Option_LabelTextHorizontalPadding + data->icld__Option_LabelTextBorderWidth) * 2) + entry->ie_TxtBuf_DisplayedLabelWidth + outline_offset) - 1;
522 rect->MinY = 0;
524 curlabel_TotalLines = entry->ie_SplitParts;
525 if (curlabel_TotalLines == 0)
526 curlabel_TotalLines = 1;
527 if (curlabel_TotalLines > data->icld__Option_LabelTextMultiLine)
528 curlabel_TotalLines = data->icld__Option_LabelTextMultiLine;
530 rect->MaxY = (((data->icld__Option_LabelTextBorderHeight + data->icld__Option_LabelTextVerticalPadding) * 2) +
531 ((data->icld_IconLabelFont->tf_YSize + outline_offset) * curlabel_TotalLines)) - 1;
533 /* Date/size sorting has the date/size appended under the entry label
534 only list regular files like this (drawers have no size/date output) */
536 entry->ie_IconListEntry.type != ST_USERDIR &&
537 ((data->icld_SortFlags & MUIV_IconList_Sort_BySize) || (data->icld_SortFlags & MUIV_IconList_Sort_ByDate))
540 SetFont(data->icld_BufferRastPort, data->icld_IconInfoFont);
542 if( (data->icld_SortFlags & MUIV_IconList_Sort_BySize) && !(data->icld_SortFlags & MUIV_IconList_Sort_ByDate) )
544 entry->ie_TxtBuf_SIZEWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_SIZE, strlen(entry->ie_TxtBuf_SIZE));
545 textwidth = entry->ie_TxtBuf_SIZEWidth;
547 else
549 if( !(data->icld_SortFlags & MUIV_IconList_Sort_BySize) && (data->icld_SortFlags & MUIV_IconList_Sort_ByDate) )
551 if( entry->ie_Flags & ICONENTRY_FLAG_TODAY )
553 entry->ie_TxtBuf_TIMEWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_TIME, strlen(entry->ie_TxtBuf_TIME));
554 textwidth = entry->ie_TxtBuf_TIMEWidth;
556 else
558 entry->ie_TxtBuf_DATEWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_DATE, strlen(entry->ie_TxtBuf_DATE));
559 textwidth = entry->ie_TxtBuf_DATEWidth;
564 if (textwidth > 0)
566 rect->MaxY = rect->MaxY + data->icld_IconInfoFont->tf_YSize + outline_offset;
567 if ((textwidth + outline_offset + ((data->icld__Option_LabelTextHorizontalPadding + data->icld__Option_LabelTextBorderWidth) * 2)) > ((rect->MaxX - rect->MinX) + 1))
568 rect->MaxX = (textwidth + outline_offset + ((data->icld__Option_LabelTextVerticalPadding + data->icld__Option_LabelTextBorderWidth) * 2)) - 1;
572 if (((rect->MaxY - rect->MinY) + 1) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = ((rect->MaxY - rect->MinY) + 1);
576 ///IconList_GetIconAreaRectangle()
577 static void IconList_GetIconAreaRectangle(Object *obj, struct IconList_DATA *data, struct IconEntry *entry, struct Rectangle *rect)
579 struct Rectangle labelrect;
580 ULONG iconlabel_Width;
581 ULONG iconlabel_Height;
583 #if defined(DEBUG_ILC_ICONPOSITIONING) && defined(DEBUG_ILC_FUNCS)
584 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
585 #endif
587 /* Get entry box width including text width */
588 memset(rect, 0, sizeof(struct Rectangle));
590 IconList_GetIconImageRectangle(obj, data, entry, rect);
592 entry->ie_AreaWidth = entry->ie_IconWidth;
593 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
595 entry->ie_AreaHeight = data->icld_IconLargestHeight;
597 else
599 entry->ie_AreaHeight = entry->ie_IconHeight;
602 IconList_GetIconLabelRectangle(obj, data, entry, &labelrect);
604 iconlabel_Width = ((labelrect.MaxX - labelrect.MinX) + 1);
605 iconlabel_Height = ((labelrect.MaxY - labelrect.MinY) + 1);
607 if (iconlabel_Width > entry->ie_AreaWidth)
608 entry->ie_AreaWidth = iconlabel_Width;
610 entry->ie_AreaHeight = entry->ie_AreaHeight + data->icld__Option_IconImageSpacing + iconlabel_Height;
612 /* Store */
613 rect->MaxX = (rect->MinX + entry->ie_AreaWidth) - 1;
614 rect->MaxY = (rect->MinY + entry->ie_AreaHeight) - 1;
616 if (entry->ie_AreaWidth > data->icld_IconAreaLargestWidth) data->icld_IconAreaLargestWidth = entry->ie_AreaWidth;
617 if (entry->ie_AreaHeight > data->icld_IconAreaLargestHeight) data->icld_IconAreaLargestHeight = entry->ie_AreaHeight;
621 static LONG FirstVisibleColumnNumber(struct IconList_DATA *data)
623 LONG i;
624 LONG retval = -1;
626 if (data->icld_LVMAttribs != NULL)
628 for(i = 0; i < NUM_COLUMNS; i++)
630 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
632 if (data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)
634 retval = i;
635 break;
640 return retval;
643 static LONG LastVisibleColumnNumber(struct IconList_DATA *data)
645 LONG i;
646 LONG retval = -1;
648 if (data->icld_LVMAttribs != NULL)
650 for(i = 0; i < NUM_COLUMNS; i++)
652 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
654 if (data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)
656 retval = i;
661 return retval;
665 static void RenderEntryField(Object *obj, struct IconList_DATA *data,
666 struct IconEntry *entry, struct Rectangle *rect,
667 LONG index, BOOL firstvis, BOOL lastvis)
669 STRPTR text;
670 struct TextExtent te;
671 ULONG fit;
673 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
675 FillPixelArray(data->icld_BufferRastPort,
676 rect->MinX, rect->MinY,
677 rect->MaxX - rect->MinX + 1, rect->MaxY - rect->MinY,
678 0x0A246A);
681 rect->MinX += ENTRY_SPACING_LEFT;
682 rect->MaxX -= ENTRY_SPACING_RIGHT;
683 rect->MinY += LINE_SPACING_TOP;
684 rect->MaxY -= LINE_SPACING_BOTTOM;
686 if (firstvis) rect->MinX += LINE_SPACING_LEFT;
687 if (lastvis) rect->MaxX -= LINE_SPACING_RIGHT;
689 if (!entry) return;
691 switch(index)
693 case INDEX_NAME:
694 text = entry->ie_IconListEntry.label;
695 break;
697 case INDEX_SIZE:
698 text = entry->ie_TxtBuf_SIZE;
699 break;
701 case INDEX_DATE:
702 text = entry->ie_TxtBuf_DATE;
703 break;
705 case INDEX_TIME:
706 text = entry->ie_TxtBuf_TIME;
707 break;
709 case INDEX_COMMENT:
710 text = entry->ie_FileInfoBlock->fib_Comment;
711 break;
713 case INDEX_PROTECTION:
714 text = entry->ie_TxtBuf_PROT;
715 break;
718 if (!text) return;
719 if (!text[0]) return;
721 fit = TextFit(data->icld_BufferRastPort, text, strlen(text), &te, NULL, 1,
722 rect->MaxX - rect->MinX + 1,
723 rect->MaxY - rect->MinY + 1);
725 if (!fit) return;
727 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[(entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? MPEN_SHINE : MPEN_TEXT], 0, JAM1);
729 switch(data->icld_LVMAttribs->lmva_ColumnAlign[index])
731 case COLUMN_ALIGN_LEFT:
732 Move(data->icld_BufferRastPort, rect->MinX, rect->MinY + data->icld_BufferRastPort->TxBaseline);
733 break;
735 case COLUMN_ALIGN_RIGHT:
736 Move(data->icld_BufferRastPort, rect->MaxX - te.te_Width, rect->MinY + data->icld_BufferRastPort->TxBaseline);
737 break;
739 case COLUMN_ALIGN_CENTER:
740 Move(data->icld_BufferRastPort, rect->MinX + (rect->MaxX - rect->MinX + 1 + 1 - te.te_Width) / 2,
741 rect->MinY + data->icld_BufferRastPort->TxBaseline);
742 break;
745 Text(data->icld_BufferRastPort, text, fit);
748 /**************************************************************************
749 Draw the entry at its position
750 **************************************************************************/
751 ///IconList__MUIM_IconList_DrawEntry()
752 IPTR IconList__MUIM_IconList_DrawEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DrawEntry *message)
754 struct IconList_DATA *data = INST_DATA(CLASS, obj);
756 BOOL outside = FALSE;
758 struct Rectangle iconrect;
759 struct Rectangle objrect;
761 LONG offsetx,offsety;
763 ULONG objX, objY, objW, objH;
764 LONG iconX, iconY;
765 ULONG iconW, iconH;
767 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
769 objX = _mleft(obj);
770 objY = _mtop(obj);
772 else
774 objX = objY = 0;
776 objW = _mright(obj) - _mleft(obj) + 1;
777 objH = _mbottom(obj) - _mtop(obj) + 1;
779 #if defined(DEBUG_ILC_ICONRENDERING)
780 D(bug("[IconList]: %s(message->entry = 0x%p)\n", __PRETTY_FUNCTION__, message->entry));
781 #endif
783 if ((!(message->entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)) ||
784 (data->icld_BufferRastPort == NULL) ||
785 (!(message->entry->ie_DiskObj)))
787 #if defined(DEBUG_ILC_ICONRENDERING)
788 D(bug("[IconList] %s: Not visible or missing DOB\n", __PRETTY_FUNCTION__));
789 #endif
790 return FALSE;
793 /* Set the dimensions of our "view" */
794 objrect.MinX = objX;
795 objrect.MinY = objY;
796 objrect.MaxX = objX + objW - 1;
797 objrect.MaxY = objY + objH - 1;
799 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
801 struct Rectangle linerect;
802 LONG x, i;
803 LONG firstvis, lastvis;
805 linerect.MinX = objX - data->icld_ViewX;
806 linerect.MaxX = objX + objW - 1; //linerect.MinX + data->width - 1;
807 linerect.MinY = (objY - data->icld_ViewY) + data->icld_LVMAttribs->lmva_HeaderHeight + (message->drawmode * data->icld_LVMAttribs->lmva_RowHeight);
808 linerect.MaxY = linerect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
810 if (!AndRectRect(&linerect, &objrect, NULL)) return;
811 // if (!MustRenderRect(data, &linerect)) return;
813 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
815 x = linerect.MinX + LINE_SPACING_LEFT;
817 firstvis = FirstVisibleColumnNumber(data);
818 lastvis = LastVisibleColumnNumber(data);
820 for(i = 0; i < NUM_COLUMNS; i++)
822 struct Rectangle field_rect;
823 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
825 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[i] & LVMCF_COLVISIBLE)) continue;
827 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
828 field_rect.MinY = linerect.MinY;
829 field_rect.MaxX = x + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1 + ((i == lastvis) ? LINE_SPACING_RIGHT : 0);
830 field_rect.MaxY = linerect.MaxY;
832 /* if (MustRenderRect(data, &field_rect))
834 if (AndRectRect(&field_rect, &objrect, NULL))
836 RenderEntryField(obj, data, message->entry, &field_rect, index,
837 (i == firstvis), (i == lastvis));
839 /* }*/
840 x += data->icld_LVMAttribs->lmva_ColumnWidth[index];
843 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_ROWDRAWTOEND) == LVMAF_ROWDRAWTOEND)
845 x += LINE_SPACING_RIGHT;
847 if (x < linerect.MaxX)
849 linerect.MinX = x;
851 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_SHINE], 0, JAM1);
852 RectFill(data->icld_BufferRastPort, linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
856 else
858 /* Get the dimensions and affected area of message->entry */
859 IconList_GetIconImageRectangle(obj, data, message->entry, &iconrect);
860 iconW = iconrect.MaxX - iconrect.MinX + 1;
861 iconH = iconrect.MaxY - iconrect.MinY + 1;
863 /* Add the relative position offset of the message->entry */
864 offsetx = objX - data->icld_ViewX + message->entry->ie_IconX;
865 /* Centre our image with our text */
866 if (message->entry->ie_IconWidth < message->entry->ie_AreaWidth)
867 offsetx += (message->entry->ie_AreaWidth - message->entry->ie_IconWidth)/2;
869 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
870 (message->entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
871 offsetx += ((data->icld_IconAreaLargestWidth - message->entry->ie_AreaWidth)/2);
873 iconrect.MinX += offsetx;
874 iconrect.MaxX += offsetx;
876 offsety = objY - data->icld_ViewY + message->entry->ie_IconY;
877 iconrect.MinY += offsety;
878 iconrect.MaxY += offsety;
880 if (!RectAndRect(&iconrect, &objrect))
882 #if defined(DEBUG_ILC_ICONRENDERING)
883 D(bug("[IconList] %s: Entry '%s' image outside of visible area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
884 #endif
885 return FALSE;
888 /* data->update_rect1 and data->update_rect2 may
889 point to rectangles to indicate that only icons
890 in any of this rectangles need to be drawn */
891 if (data->update_rect1)
893 if (!RectAndRect(&iconrect, data->update_rect1)) outside = TRUE;
896 if (data->update_rect2)
898 if (data->update_rect1)
900 if ((outside == TRUE) && RectAndRect(&iconrect, data->update_rect2))
901 outside = FALSE;
903 else
905 if (!RectAndRect(&iconrect, data->update_rect2))
906 outside = TRUE;
910 if (outside == TRUE)
912 #if defined(DEBUG_ILC_ICONRENDERING)
913 D(bug("[IconList] %s: Entry '%s' image outside of update area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
914 #endif
915 return FALSE;
918 if (message->drawmode == ICONENTRY_DRAWMODE_NONE) return TRUE;
920 // Center entry image
921 iconX = iconrect.MinX - objX + data->icld_DrawOffsetX;
922 iconY = iconrect.MinY - objY + data->icld_DrawOffsetY;
924 #if defined(DEBUG_ILC_ICONRENDERING)
925 D(bug("[IconList] %s: DrawIconState('%s') .. %d, %d\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label, iconX, iconY));
926 #endif
927 DrawIconStateA
929 data->icld_BufferRastPort, message->entry->ie_DiskObj, NULL,
930 iconX,
931 iconY,
932 (message->entry->ie_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
933 __iconList_DrawIconStateTags
935 #if defined(DEBUG_ILC_ICONRENDERING)
936 D(bug("[IconList] %s: DrawIconState Done\n", __PRETTY_FUNCTION__));
937 #endif
940 return TRUE;
944 ///IconList__LabelFunc_SplitLabel()
945 static void IconList__LabelFunc_SplitLabel(Object *obj, struct IconList_DATA *data, struct IconEntry *entry)
947 ULONG labelSplit_MaxLabelLineLength = data->icld__Option_LabelTextMaxLen;
948 ULONG labelSplit_LabelLength = strlen(entry->ie_IconListEntry.label);
949 ULONG txwidth;
950 // ULONG labelSplit_FontY = data->icld_IconLabelFont->tf_YSize;
951 int labelSplit_CharsDone, labelSplit_CharsSplit;
952 ULONG labelSplit_CurSplitWidth;
954 if ((data->icld__Option_TrimVolumeNames) &&
955 ((entry->ie_IconListEntry.type == ST_ROOT) && (entry->ie_IconListEntry.label[labelSplit_LabelLength - 1] == ':')))
956 labelSplit_LabelLength--;
958 if (labelSplit_MaxLabelLineLength >= labelSplit_LabelLength)
960 #if defined(DEBUG_ILC_ICONRENDERING)
961 D(bug("[IconList]: %s: Label'%s' doesnt need split (onyl %d chars)\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label, labelSplit_LabelLength));
962 #endif
963 return;
966 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
967 txwidth = TextLength(data->icld_BufferRastPort, entry->ie_IconListEntry.label, labelSplit_MaxLabelLineLength);
968 #if defined(DEBUG_ILC_ICONRENDERING)
969 D(bug("[IconList]: %s: txwidth = %d\n", __PRETTY_FUNCTION__, txwidth));
970 #endif
971 entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, 256);
972 memset(entry->ie_TxtBuf_DisplayedLabel, 0, 256);
973 entry->ie_SplitParts = 0;
975 labelSplit_CharsDone = 0;
976 labelSplit_CharsSplit = 0;
978 while (labelSplit_CharsDone < labelSplit_LabelLength)
980 ULONG labelSplit_CurSplitLength = labelSplit_LabelLength - labelSplit_CharsDone;
981 IPTR labelSplit_SplitStart = (IPTR)(entry->ie_IconListEntry.label + labelSplit_CharsDone);
982 int tmp_checkoffs = 0;
983 IPTR labelSplit_RemainingCharsAfterSplit;
984 IPTR labelSplit_CurSplitDest;
986 while (*(char *)(labelSplit_SplitStart) == ' ')
988 //Skip preceding spaces..
989 labelSplit_SplitStart = labelSplit_SplitStart + 1;
990 labelSplit_CurSplitLength = labelSplit_CurSplitLength - 1;
991 labelSplit_CharsDone = labelSplit_CharsDone + 1;
994 while(TextLength(data->icld_BufferRastPort, (char *)labelSplit_SplitStart, labelSplit_CurSplitLength) < txwidth) labelSplit_CurSplitLength++;
995 while(TextLength(data->icld_BufferRastPort, (char *)labelSplit_SplitStart, labelSplit_CurSplitLength) > txwidth) labelSplit_CurSplitLength--;
996 #if defined(DEBUG_ILC_ICONRENDERING)
997 D(bug("[IconList]: %s: labelSplit_CurSplitLength = %d\n", __PRETTY_FUNCTION__, labelSplit_CurSplitLength));
998 #endif
1000 #if defined(DEBUG_ILC_ICONRENDERING)
1001 D(bug("[IconList]: %s: Attempting to find neat split ", __PRETTY_FUNCTION__));
1002 #endif
1003 while(tmp_checkoffs < (labelSplit_CurSplitLength - ILC_ICONLABEL_SHORTEST))
1005 #if defined(DEBUG_ILC_ICONRENDERING)
1006 D(bug("%d", tmp_checkoffs));
1007 #endif
1008 labelSplit_RemainingCharsAfterSplit = labelSplit_LabelLength - (labelSplit_CharsDone + labelSplit_CurSplitLength);
1010 if ((labelSplit_CurSplitLength - tmp_checkoffs) > ILC_ICONLABEL_SHORTEST)
1012 #if defined(DEBUG_ILC_ICONRENDERING)
1013 D(bug("<"));
1014 #endif
1015 if ((*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == ' ') ||
1016 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == '.') ||
1017 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength - tmp_checkoffs) == '-'))
1019 #if defined(DEBUG_ILC_ICONRENDERING)
1020 D(bug("!"));
1021 #endif
1022 labelSplit_CurSplitLength = labelSplit_CurSplitLength - tmp_checkoffs;
1023 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit - tmp_checkoffs;
1024 tmp_checkoffs = 0;
1025 break;
1029 if ((labelSplit_RemainingCharsAfterSplit - tmp_checkoffs) < 0)
1031 #if defined(DEBUG_ILC_ICONRENDERING)
1032 D(bug("="));
1033 #endif
1034 labelSplit_CurSplitLength = labelSplit_CurSplitLength + tmp_checkoffs;
1035 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit + tmp_checkoffs;
1036 tmp_checkoffs = 0;
1037 break;
1040 if ((labelSplit_RemainingCharsAfterSplit - tmp_checkoffs) >= ILC_ICONLABEL_SHORTEST)
1042 #if defined(DEBUG_ILC_ICONRENDERING)
1043 D(bug(">"));
1044 #endif
1045 if ((*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == ' ') ||
1046 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == '.') ||
1047 (*(char *)(labelSplit_SplitStart + labelSplit_CurSplitLength + tmp_checkoffs) == '-'))
1049 #if defined(DEBUG_ILC_ICONRENDERING)
1050 D(bug("!"));
1051 #endif
1052 labelSplit_CurSplitLength = labelSplit_CurSplitLength + tmp_checkoffs;
1053 labelSplit_RemainingCharsAfterSplit = labelSplit_RemainingCharsAfterSplit + tmp_checkoffs;
1054 tmp_checkoffs = 0;
1055 break;
1059 tmp_checkoffs = tmp_checkoffs + 1;
1061 #if defined(DEBUG_ILC_ICONRENDERING)
1062 D(bug("\n"));
1063 #endif
1064 if (tmp_checkoffs != 0)
1066 #if defined(DEBUG_ILC_ICONRENDERING)
1067 D(bug("[IconList]: %s: Couldnt find neat split : Still %d chars\n", __PRETTY_FUNCTION__, labelSplit_RemainingCharsAfterSplit));
1068 #endif
1069 if (labelSplit_RemainingCharsAfterSplit <= ILC_ICONLABEL_SHORTEST)
1071 labelSplit_CurSplitLength = labelSplit_CurSplitLength + (labelSplit_RemainingCharsAfterSplit - ILC_ICONLABEL_SHORTEST);
1074 if ((labelSplit_CharsDone + labelSplit_CurSplitLength) > labelSplit_LabelLength) labelSplit_CurSplitLength = labelSplit_LabelLength - labelSplit_CharsDone;
1076 labelSplit_CurSplitDest = (IPTR)(entry->ie_TxtBuf_DisplayedLabel + labelSplit_CharsSplit + entry->ie_SplitParts);
1078 strncpy((char *)labelSplit_CurSplitDest, (char *)labelSplit_SplitStart, labelSplit_CurSplitLength);
1080 labelSplit_CurSplitWidth = TextLength(data->icld_BufferRastPort, (char *)labelSplit_CurSplitDest, labelSplit_CurSplitLength);
1082 entry->ie_SplitParts = entry->ie_SplitParts + 1;
1084 labelSplit_CharsDone = labelSplit_CharsDone + labelSplit_CurSplitLength;
1085 labelSplit_CharsSplit = labelSplit_CharsSplit + labelSplit_CurSplitLength;
1087 if (labelSplit_CurSplitWidth > entry->ie_TxtBuf_DisplayedLabelWidth) entry->ie_TxtBuf_DisplayedLabelWidth = labelSplit_CurSplitWidth;
1089 if ((entry->ie_SplitParts <= 1) && entry->ie_TxtBuf_DisplayedLabel)
1091 FreeVecPooled(data->icld_Pool, entry->ie_TxtBuf_DisplayedLabel);
1092 entry->ie_TxtBuf_DisplayedLabel = NULL;
1093 entry->ie_SplitParts = 0;
1095 // if ((labelSplit_FontY * entry->ie_SplitParts) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = (labelSplit_FontY * entry->ie_SplitParts);
1099 ///IconList__LabelFunc_CreateLabel()
1100 static IPTR IconList__LabelFunc_CreateLabel(Object *obj, struct IconList_DATA *data, struct IconEntry *entry)
1102 #if defined(DEBUG_ILC_ICONRENDERING) && defined(DEBUG_ILC_FUNCS)
1103 D(bug("[IconList]: %s('%s')\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.label));
1104 #endif
1105 if (entry->ie_TxtBuf_DisplayedLabel)
1107 FreeVecPooled(data->icld_Pool, entry->ie_TxtBuf_DisplayedLabel);
1108 entry->ie_TxtBuf_DisplayedLabel = NULL;
1109 entry->ie_SplitParts = 0;
1112 if (data->icld__Option_LabelTextMultiLine > 1)
1114 #if defined(DEBUG_ILC_ICONRENDERING)
1115 D(bug("[IconList]: %s: Attempting to split label ..\n", __PRETTY_FUNCTION__));
1116 #endif
1117 IconList__LabelFunc_SplitLabel(obj, data, entry);
1120 if (entry->ie_TxtBuf_DisplayedLabel == NULL)
1122 ULONG ie_LabelLength = strlen(entry->ie_IconListEntry.label);
1123 entry->ie_SplitParts = 1;
1125 #if defined(DEBUG_ILC_ICONRENDERING)
1126 D(bug("[IconList]: %s: Building unsplit label (len = %d) ..\n", __PRETTY_FUNCTION__, ie_LabelLength));
1127 #endif
1129 if ((data->icld__Option_TrimVolumeNames) &&
1130 ((entry->ie_IconListEntry.type == ST_ROOT) && (entry->ie_IconListEntry.label[ie_LabelLength - 1] == ':')))
1131 ie_LabelLength--;
1133 if(ie_LabelLength > data->icld__Option_LabelTextMaxLen)
1135 if (!(entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, data->icld__Option_LabelTextMaxLen + 1)))
1137 return (IPTR)NULL;
1139 memset(entry->ie_TxtBuf_DisplayedLabel, 0, data->icld__Option_LabelTextMaxLen + 1);
1140 strncpy(entry->ie_TxtBuf_DisplayedLabel, entry->ie_IconListEntry.label, data->icld__Option_LabelTextMaxLen - 3);
1141 strcat(entry->ie_TxtBuf_DisplayedLabel , " ..");
1143 else
1145 if (!(entry->ie_TxtBuf_DisplayedLabel = AllocVecPooled(data->icld_Pool, ie_LabelLength + 1)))
1147 return (IPTR)NULL;
1149 memset(entry->ie_TxtBuf_DisplayedLabel, 0, ie_LabelLength + 1);
1150 strncpy(entry->ie_TxtBuf_DisplayedLabel, entry->ie_IconListEntry.label, ie_LabelLength );
1152 entry->ie_TxtBuf_DisplayedLabelWidth = TextLength(data->icld_BufferRastPort, entry->ie_TxtBuf_DisplayedLabel, strlen(entry->ie_TxtBuf_DisplayedLabel));
1153 // if ((data->icld_IconLabelFont->tf_YSize) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = data->icld_IconLabelFont->tf_YSize;
1156 // if (entry->ie_TxtBuf_DisplayedLabelWidth > data->icld_LabelLargestWidth) data->icld_LabelLargestWidth = entry->ie_TxtBuf_DisplayedLabelWidth;
1158 return (IPTR)entry->ie_TxtBuf_DisplayedLabel;
1162 ///IconList__HookFunc_UpdateLabelsFunc()
1163 AROS_UFH3(
1164 void, IconList__HookFunc_UpdateLabelsFunc,
1165 AROS_UFHA(struct Hook *, hook, A0),
1166 AROS_UFHA(APTR *, obj, A2),
1167 AROS_UFHA(APTR, param, A1)
1170 AROS_USERFUNC_INIT
1172 /* Get our private data */
1173 Class *CLASS = *( Class **)param;
1174 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1176 #if defined(DEBUG_ILC_LASSO) && defined(DEBUG_ILC_FUNCS)
1177 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1178 #endif
1180 if (((data->icld__Option_LabelTextMaxLen != data->icld__Option_LastLabelTextMaxLen) &&
1181 (data->icld__Option_LabelTextMultiLine > 1)) ||
1182 (data->icld__Option_LabelTextMultiLine != data->icld__Option_LastLabelTextMultiLine));
1184 struct IconEntry *iconentry_Current = NULL;
1185 #if defined(__AROS__)
1186 ForeachNode(&data->icld_IconList, iconentry_Current)
1187 #else
1188 Foreach_Node(&data->icld_IconList, iconentry_Current);
1189 #endif
1191 IconList__LabelFunc_CreateLabel((Object *)obj, data, iconentry_Current);
1195 data->icld__Option_LastLabelTextMaxLen = data->icld__Option_LabelTextMaxLen;
1196 data->icld__Option_LastLabelTextMultiLine = data->icld__Option_LabelTextMultiLine;
1198 AROS_USERFUNC_EXIT
1202 ///IconList__MUIM_IconList_DrawEntryLabel()
1203 IPTR IconList__MUIM_IconList_DrawEntryLabel(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DrawEntry *message)
1205 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1207 STRPTR buf = NULL;
1208 BOOL outside = FALSE;
1210 struct Rectangle iconlabelrect;
1211 struct Rectangle objrect;
1213 ULONG txtbox_width = 0;
1214 LONG tx,ty,offsetx,offsety;
1215 LONG txwidth; // txheight;
1217 ULONG objX, objY, objW, objH;
1218 LONG labelX, labelY;
1219 ULONG labelW, labelH;
1221 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1222 return FALSE;
1224 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
1226 objX = _mleft(obj);
1227 objY = _mtop(obj);
1229 else
1231 objX = objY = 0;
1233 objW = _mright(obj) - _mleft(obj) + 1;
1234 objH = _mbottom(obj) - _mtop(obj) + 1;
1236 ULONG txtarea_width;
1237 ULONG curlabel_TotalLines, curlabel_CurrentLine, offset_y;
1239 #if defined(DEBUG_ILC_ICONRENDERING) && defined(DEBUG_ILC_FUNCS)
1240 D(bug("[IconList]: %s(message->entry = 0x%p), '%s'\n", __PRETTY_FUNCTION__, message->entry, message->entry->ie_IconListEntry.label));
1241 #endif
1243 if ((!(message->entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)) ||
1244 (data->icld_BufferRastPort == NULL) ||
1245 (!(message->entry->ie_DiskObj)))
1247 #if defined(DEBUG_ILC_ICONRENDERING)
1248 D(bug("[IconList] %s: Not visible or missing DOB\n", __PRETTY_FUNCTION__));
1249 #endif
1250 return FALSE;
1253 /* Get the dimensions and affected area of message->entry's label */
1254 IconList_GetIconLabelRectangle(obj, data, message->entry, &iconlabelrect);
1255 labelW = iconlabelrect.MaxX - iconlabelrect.MinX + 1;
1256 labelH = iconlabelrect.MaxY - iconlabelrect.MinY + 1;
1258 /* Add the relative position offset of the message->entry's label */
1259 offsetx = (objX - data->icld_ViewX) + message->entry->ie_IconX;
1260 txtbox_width = (iconlabelrect.MaxX - iconlabelrect.MinX) + 1;
1262 if (txtbox_width < message->entry->ie_AreaWidth)
1263 offsetx += ((message->entry->ie_AreaWidth - txtbox_width)/2);
1265 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1266 (message->entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
1267 offsetx += ((data->icld_IconAreaLargestWidth - message->entry->ie_AreaWidth)/2);
1269 iconlabelrect.MinX += offsetx;
1270 iconlabelrect.MaxX += offsetx;
1272 offsety = (objY - data->icld_ViewY) + message->entry->ie_IconY + data->icld__Option_IconImageSpacing;
1273 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1275 offsety = offsety + data->icld_IconLargestHeight;
1277 else
1279 offsety = offsety + message->entry->ie_IconHeight;
1281 iconlabelrect.MinY += offsety;
1282 iconlabelrect.MaxY += offsety;
1284 /* Add the relative position of the window */
1285 objrect.MinX = objX;
1286 objrect.MinY = objX;
1287 objrect.MaxX = objX + objW;
1288 objrect.MaxY = objY + objH;
1290 if (!RectAndRect(&iconlabelrect, &objrect))
1292 #if defined(DEBUG_ILC_ICONRENDERING)
1293 (bug("[IconList] %s: Entry '%s' label outside of visible area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1294 #endif
1295 return FALSE;
1298 /* data->update_rect1 and data->update_rect2 may
1299 point to rectangles to indicate that only icons
1300 in any of this rectangles need to be drawn */
1301 if (data->update_rect1)
1303 if (!RectAndRect(&iconlabelrect, data->update_rect1))
1304 outside = TRUE;
1307 if (data->update_rect2)
1309 if (data->update_rect1)
1311 if ((outside == TRUE) && RectAndRect(&iconlabelrect, data->update_rect2))
1312 outside = FALSE;
1314 else
1316 if (!RectAndRect(&iconlabelrect, data->update_rect2))
1317 outside = TRUE;
1321 if (outside == TRUE)
1323 #if defined(DEBUG_ILC_ICONRENDERING)
1324 D(bug("[IconList] %s: Entry '%s' label outside of update area .. skipping\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label));
1325 #endif
1326 return FALSE;
1329 if (message->drawmode == ICONENTRY_DRAWMODE_NONE)
1330 return TRUE;
1332 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_TEXT], 0, JAM1);
1334 iconlabelrect.MinX = (iconlabelrect.MinX - objX) + data->icld_DrawOffsetX;
1335 iconlabelrect.MinY = (iconlabelrect.MinY - objY) + data->icld_DrawOffsetY;
1336 iconlabelrect.MaxX = (iconlabelrect.MaxX - objX) + data->icld_DrawOffsetX;
1337 iconlabelrect.MaxY = (iconlabelrect.MaxY - objY) + data->icld_DrawOffsetY;
1339 labelX = iconlabelrect.MinX + data->icld__Option_LabelTextBorderWidth + data->icld__Option_LabelTextHorizontalPadding;
1340 labelY = iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight + data->icld__Option_LabelTextVerticalPadding;
1342 txtarea_width = txtbox_width - ((data->icld__Option_LabelTextBorderWidth + data->icld__Option_LabelTextHorizontalPadding) * 2);
1344 #if defined(DEBUG_ILC_ICONRENDERING)
1345 D(bug("[IconList] %s: Drawing Label '%s' .. %d, %d\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.label, labelX, labelY));
1346 #endif
1347 if (message->entry->ie_IconListEntry.label && message->entry->ie_TxtBuf_DisplayedLabel)
1349 char *curlabel_StrPtr;
1351 if ((message->entry->ie_Flags & ICONENTRY_FLAG_FOCUS) && ((BOOL)XGET(_win(obj), MUIA_Window_Activate)))
1353 //Draw the focus box around the selected label ..
1354 if (data->icld__Option_LabelTextBorderHeight > 0)
1356 InvertPixelArray(data->icld_BufferRastPort,
1357 iconlabelrect.MinX, iconlabelrect.MinY,
1358 (iconlabelrect.MaxX - iconlabelrect.MinX) + 1, data->icld__Option_LabelTextBorderHeight);
1360 InvertPixelArray(data->icld_BufferRastPort,
1361 iconlabelrect.MinX, iconlabelrect.MaxY - (data->icld__Option_LabelTextBorderHeight - 1),
1362 (iconlabelrect.MaxX - iconlabelrect.MinX) + 1, data->icld__Option_LabelTextBorderHeight);
1364 if (data->icld__Option_LabelTextBorderWidth > 0)
1366 InvertPixelArray(data->icld_BufferRastPort,
1367 iconlabelrect.MinX, iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight,
1368 data->icld__Option_LabelTextBorderWidth, (((iconlabelrect.MaxY - iconlabelrect.MinY) + 1) - (data->icld__Option_LabelTextBorderHeight * 2)));
1370 InvertPixelArray(data->icld_BufferRastPort,
1371 iconlabelrect.MaxX - (data->icld__Option_LabelTextBorderWidth - 1), iconlabelrect.MinY + data->icld__Option_LabelTextBorderHeight,
1372 data->icld__Option_LabelTextBorderWidth, (((iconlabelrect.MaxY - iconlabelrect.MinY) + 1) - (data->icld__Option_LabelTextBorderHeight * 2)));
1376 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
1378 curlabel_TotalLines = message->entry->ie_SplitParts;
1379 curlabel_CurrentLine = 0;
1381 if (curlabel_TotalLines == 0)
1382 curlabel_TotalLines = 1;
1384 if (!(data->icld__Option_LabelTextMultiLineOnFocus) || (data->icld__Option_LabelTextMultiLineOnFocus && (message->entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
1386 if (curlabel_TotalLines > data->icld__Option_LabelTextMultiLine)
1387 curlabel_TotalLines = data->icld__Option_LabelTextMultiLine;
1389 else
1390 curlabel_TotalLines = 1;
1392 curlabel_StrPtr = message->entry->ie_TxtBuf_DisplayedLabel;
1394 ty = labelY - 1;
1396 #if defined(DEBUG_ILC_ICONRENDERING)
1397 D(bug("[IconList] %s: Font YSize %d Baseline %d\n", __PRETTY_FUNCTION__,data->icld_IconLabelFont->tf_YSize, data->icld_IconLabelFont->tf_Baseline));
1398 #endif
1399 for (curlabel_CurrentLine = 0; curlabel_CurrentLine < curlabel_TotalLines; curlabel_CurrentLine++)
1401 ULONG ie_LabelLength;
1403 if (curlabel_CurrentLine > 0) curlabel_StrPtr = curlabel_StrPtr + strlen(curlabel_StrPtr) + 1;
1404 if ((curlabel_CurrentLine >= (curlabel_TotalLines -1)) && (curlabel_TotalLines < message->entry->ie_SplitParts))
1406 char *tmpLine = curlabel_StrPtr;
1407 ULONG tmpLen = strlen(tmpLine);
1409 if ((curlabel_StrPtr = AllocVecPooled(data->icld_Pool, tmpLen + 1)) != NULL)
1411 memset(curlabel_StrPtr, 0, tmpLen + 1);
1412 strncpy(curlabel_StrPtr, tmpLine, tmpLen - 3);
1413 strcat(curlabel_StrPtr , " ..");
1415 else
1416 return FALSE;
1420 ie_LabelLength = strlen(curlabel_StrPtr);
1421 offset_y = 0;
1423 // Center message->entry's label
1424 tx = (labelX + (message->entry->ie_TxtBuf_DisplayedLabelWidth / 2) - (TextLength(data->icld_BufferRastPort, curlabel_StrPtr, strlen(curlabel_StrPtr)) / 2));
1426 if (message->entry->ie_TxtBuf_DisplayedLabelWidth < txtarea_width)
1427 tx += ((txtarea_width - message->entry->ie_TxtBuf_DisplayedLabelWidth)/2);
1429 ty = ty + data->icld_IconLabelFont->tf_YSize;
1431 switch ( data->icld__Option_LabelTextMode )
1433 case ICON_TEXTMODE_DROPSHADOW:
1434 SetAPen(data->icld_BufferRastPort, data->icld_LabelShadowPen);
1435 Move(data->icld_BufferRastPort, tx + 1, ty + 1);
1436 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1437 offset_y = 1;
1438 case ICON_TEXTMODE_PLAIN:
1439 SetAPen(data->icld_BufferRastPort, data->icld_LabelPen);
1440 Move(data->icld_BufferRastPort, tx, ty);
1441 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1442 break;
1444 default:
1445 // Outline mode:
1446 SetSoftStyle(data->icld_BufferRastPort, FSF_BOLD, AskSoftStyle(data->icld_BufferRastPort));
1448 SetAPen(data->icld_BufferRastPort, data->icld_LabelShadowPen);
1449 Move(data->icld_BufferRastPort, tx + 1, ty );
1450 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1451 Move(data->icld_BufferRastPort, tx - 1, ty );
1452 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1453 Move(data->icld_BufferRastPort, tx, ty + 1);
1454 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1455 Move(data->icld_BufferRastPort, tx, ty - 1);
1456 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1458 SetAPen(data->icld_BufferRastPort, data->icld_LabelPen);
1459 Move(data->icld_BufferRastPort, tx , ty );
1460 Text(data->icld_BufferRastPort, curlabel_StrPtr, ie_LabelLength);
1462 SetSoftStyle(data->icld_BufferRastPort, FS_NORMAL, AskSoftStyle(data->icld_BufferRastPort));
1463 offset_y = 2;
1464 break;
1466 if ((curlabel_CurrentLine >= (curlabel_TotalLines -1)) && (curlabel_TotalLines < message->entry->ie_SplitParts))
1468 FreeVecPooled(data->icld_Pool, curlabel_StrPtr);
1470 ty = ty + offset_y;
1473 /*date/size sorting has the date/size appended under the message->entry label*/
1475 if ((message->entry->ie_IconListEntry.type != ST_USERDIR) && ((data->icld_SortFlags & (MUIV_IconList_Sort_BySize|MUIV_IconList_Sort_ByDate)) != 0))
1477 buf = NULL;
1478 SetFont(data->icld_BufferRastPort, data->icld_IconInfoFont);
1480 if ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == MUIV_IconList_Sort_BySize)
1482 buf = message->entry->ie_TxtBuf_SIZE;
1483 txwidth = message->entry->ie_TxtBuf_SIZEWidth;
1485 else if ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == MUIV_IconList_Sort_ByDate)
1487 if (message->entry->ie_Flags & ICONENTRY_FLAG_TODAY)
1489 buf = message->entry->ie_TxtBuf_TIME;
1490 txwidth = message->entry->ie_TxtBuf_TIMEWidth;
1492 else
1494 buf = message->entry->ie_TxtBuf_DATE;
1495 txwidth = message->entry->ie_TxtBuf_DATEWidth;
1499 if (buf)
1501 ULONG ie_LabelLength = strlen(buf);
1502 tx = labelX;
1504 if (txwidth < txtarea_width)
1505 tx += ((txtarea_width - txwidth)/2);
1507 ty = labelY + ((data->icld__Option_LabelTextVerticalPadding + data->icld_IconLabelFont->tf_YSize ) * curlabel_TotalLines) + data->icld_IconInfoFont->tf_YSize;
1509 switch ( data->icld__Option_LabelTextMode )
1511 case ICON_TEXTMODE_DROPSHADOW:
1512 SetAPen(data->icld_BufferRastPort, data->icld_InfoShadowPen);
1513 Move(data->icld_BufferRastPort, tx + 1, ty + 1); Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1514 case ICON_TEXTMODE_PLAIN:
1515 SetAPen(data->icld_BufferRastPort, data->icld_InfoPen);
1516 Move(data->icld_BufferRastPort, tx, ty); Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1517 break;
1519 default:
1520 // Outline mode..
1521 SetSoftStyle(data->icld_BufferRastPort, FSF_BOLD, AskSoftStyle(data->icld_BufferRastPort));
1522 SetAPen(data->icld_BufferRastPort, data->icld_InfoShadowPen);
1524 Move(data->icld_BufferRastPort, tx + 1, ty );
1525 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1526 Move(data->icld_BufferRastPort, tx - 1, ty );
1527 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1528 Move(data->icld_BufferRastPort, tx, ty - 1 );
1529 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1530 Move(data->icld_BufferRastPort, tx, ty + 1 );
1531 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1533 SetAPen(data->icld_BufferRastPort, data->icld_InfoPen);
1535 Move(data->icld_BufferRastPort, tx, ty );
1536 Text(data->icld_BufferRastPort, buf, ie_LabelLength);
1538 SetSoftStyle(data->icld_BufferRastPort, FS_NORMAL, AskSoftStyle(data->icld_BufferRastPort));
1539 break;
1545 return TRUE;
1548 /**************************************************************************
1550 **************************************************************************/
1551 ///IconList__MUIM_IconList_RethinkDimensions()
1552 IPTR IconList__MUIM_IconList_RethinkDimensions(struct IClass *CLASS, Object *obj, struct MUIP_IconList_RethinkDimensions *message)
1554 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1556 struct IconEntry *entry = NULL;
1557 LONG maxx = 0,
1558 maxy = 0;
1559 struct Rectangle icon_rect;
1561 #if defined(DEBUG_ILC_ICONPOSITIONING) && defined(DEBUG_ILC_FUNCS)
1562 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1563 #endif
1565 if (message->singleicon != NULL)
1567 entry = message->singleicon;
1568 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1570 maxy = data->icld_LVMAttribs->lmva_RowHeight;
1571 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
1573 maxy += data->icld_LVMAttribs->lmva_HeaderHeight;
1576 else
1578 maxx = data->icld_AreaWidth - 1,
1579 maxy = data->icld_AreaHeight - 1;
1582 #if defined(DEBUG_ILC_ICONPOSITIONING)
1583 D(bug("[IconList] %s: SingleIcon - maxx = %d, maxy = %d\n", __PRETTY_FUNCTION__, maxx, maxy));
1584 #endif
1586 else
1588 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1590 maxy = data->icld_LVMAttribs->lmva_RowHeight;
1591 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
1593 maxy += data->icld_LVMAttribs->lmva_HeaderHeight;
1596 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1599 while (entry != NULL)
1601 if (entry->ie_DiskObj &&
1602 (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1604 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1606 maxy += data->icld_LVMAttribs->lmva_RowHeight;
1608 else
1610 IconList_GetIconAreaRectangle(obj, data, entry, &icon_rect);
1612 icon_rect.MaxX += entry->ie_IconX + data->icld__Option_IconHorizontalSpacing;
1613 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
1614 (entry->ie_AreaWidth < data->icld_IconAreaLargestWidth))
1615 icon_rect.MaxX += (data->icld_IconAreaLargestWidth - entry->ie_AreaWidth);
1617 icon_rect.MaxY += entry->ie_IconY + data->icld__Option_IconVerticalSpacing;
1619 if (icon_rect.MaxX > maxx) maxx = icon_rect.MaxX;
1620 if (icon_rect.MaxY > maxy) maxy = icon_rect.MaxY;
1624 if (message->singleicon)
1625 break;
1627 entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode);
1630 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
1632 int col;
1634 for(col = 0; col < NUM_COLUMNS; col++)
1636 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[col];
1638 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
1640 maxx += data->icld_LVMAttribs->lmva_ColumnWidth[index];
1644 /* update our view when max x/y have changed */
1645 if (maxx + 1 != data->icld_AreaWidth)
1647 data->icld_AreaWidth = maxx + 1;
1648 SET(obj, MUIA_IconList_Width, data->icld_AreaWidth);
1650 if (maxy + 1 != data->icld_AreaHeight)
1652 data->icld_AreaHeight = maxy + 1;
1653 SET(obj, MUIA_IconList_Height, data->icld_AreaHeight);
1656 return TRUE;
1659 ///IconList__MUIM_IconList_PositionIcons()
1660 /**************************************************************************
1661 MUIM_PositionIcons - Place icons with NO_ICON_POSITION coords somewhere
1662 **************************************************************************/
1663 IPTR IconList__MUIM_IconList_PositionIcons(struct IClass *CLASS, Object *obj, struct MUIP_IconList_PositionIcons *message)
1665 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1666 struct IconEntry *entry = NULL, *pass_first = NULL;
1668 int left = data->icld__Option_IconHorizontalSpacing;
1669 int top = data->icld__Option_IconVerticalSpacing;
1670 int cur_x = left;
1671 int cur_y = top;
1672 int gridx = 0;
1673 int gridy = 0;
1674 int maxw = 0; // Widest & Talest entry in a column or row.
1675 int maxh = 0;
1677 BOOL next;
1678 struct Rectangle iconrect;
1680 #if defined(DEBUG_ILC_ICONPOSITIONING) && defined(DEBUG_ILC_FUNCS)
1681 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1682 #endif
1684 // Now go to the actual positioning
1685 entry = (struct IconEntry *)GetHead(&data->icld_IconList);
1686 while (entry != NULL)
1688 next = FALSE;
1689 if ((entry->ie_DiskObj != NULL) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
1691 next = TRUE;
1692 entry->ie_IconX = cur_x;
1693 entry->ie_IconY = cur_y;
1695 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
1697 if (data->icld_SelectionLastClicked == NULL) data->icld_SelectionLastClicked = entry;
1698 if (data->icld_FocusIcon == NULL) data->icld_FocusIcon = entry;
1701 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1703 maxw = data->icld_IconAreaLargestWidth + data->icld__Option_IconHorizontalSpacing;
1704 maxh = data->icld_IconLargestHeight + data->icld__Option_IconImageSpacing + data->icld_LabelLargestHeight + data->icld__Option_IconVerticalSpacing;
1705 gridx = maxw;
1706 gridy = maxh;
1708 else
1710 if (!(pass_first)) pass_first = entry;
1712 IconList_GetIconAreaRectangle(obj, data, entry, &iconrect);
1714 if (entry->ie_AreaWidth < maxw)
1715 entry->ie_IconX += ( maxw - entry->ie_AreaWidth ) / 2;
1717 if ((maxw < entry->ie_AreaWidth) || (maxh < entry->ie_AreaHeight))
1719 if (maxw < entry->ie_AreaWidth) maxw = entry->ie_AreaWidth;
1720 if (maxh < entry->ie_AreaHeight) maxh = entry->ie_AreaHeight;
1721 if (pass_first != entry)
1723 entry = pass_first;
1724 cur_x = entry->ie_IconX;
1725 cur_y = entry->ie_IconY;
1726 continue;
1730 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1732 gridx = maxw;
1733 gridy = entry->ie_AreaHeight + data->icld__Option_IconHorizontalSpacing;
1735 else
1737 gridx = entry->ie_AreaWidth + data->icld__Option_IconVerticalSpacing;
1738 gridy = maxh;
1742 if ((entry = (struct IconEntry *)GetSucc(&entry->ie_IconNode)) != NULL)
1744 if (next == TRUE)
1746 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
1748 cur_y += gridy;
1750 if ((cur_y >= data->icld_ViewHeight) ||
1751 ((data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH) && ((cur_y + entry->ie_AreaHeight - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight)) ||
1752 ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) && ((cur_y + data->icld_IconAreaLargestHeight - data->icld__Option_IconBorderOverlap) >= data->icld_ViewHeight)))
1754 cur_x += maxw;
1755 cur_y = top;
1756 pass_first = NULL;
1757 maxw = 0;
1760 else
1762 cur_x += gridx;
1764 if ((cur_x >= data->icld_ViewWidth) ||
1765 ((data->icld__Option_IconListMode == ICON_LISTMODE_ROUGH) && ((cur_x + entry->ie_AreaWidth - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth)) ||
1766 ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) && ((cur_x + data->icld_IconAreaLargestWidth - data->icld__Option_IconBorderOverlap) >= data->icld_ViewWidth)))
1768 cur_x = left;
1769 cur_y += maxh;
1770 pass_first = NULL;
1771 maxh = 0;
1773 else if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
1781 DoMethod(obj, MUIM_IconList_RethinkDimensions, NULL);
1782 return (IPTR)NULL;
1786 ///OM_NEW()
1787 /**************************************************************************
1788 OM_NEW
1789 **************************************************************************/
1790 IPTR IconList__OM_NEW(struct IClass *CLASS, Object *obj, struct opSet *message)
1792 struct IconList_DATA *data = NULL;
1793 struct TextFont *icl_WindowFont = NULL;
1794 // struct RastPort *icl_RastPort = NULL;
1795 int i;
1797 #if defined(DEBUG_ILC_FUNCS)
1798 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1799 #endif
1801 icl_WindowFont = (struct TextFont *) GetTagData(MUIA_Font, (IPTR) NULL, message->ops_AttrList);
1803 obj = (Object *)DoSuperNewTags(CLASS, obj, NULL,
1804 MUIA_FillArea, FALSE,
1805 MUIA_Dropable, TRUE,
1806 MUIA_Font, MUIV_Font_Tiny,
1807 TAG_MORE, (IPTR) message->ops_AttrList);
1809 if (!obj) return FALSE;
1811 data = INST_DATA(CLASS, obj);
1813 data->icld_Pool = CreatePool(0,4096,4096);
1814 if (!data->icld_Pool)
1816 CoerceMethod(CLASS,obj,OM_DISPOSE);
1817 return (IPTR)NULL;
1820 #if defined(DEBUG_ILC_FUNCS)
1821 D(bug("[IconList] %s: SELF = 0x%p, muiRenderInfo = 0x%p\n", __PRETTY_FUNCTION__, obj, muiRenderInfo(obj)));
1822 #endif
1823 NewList((struct List*)&data->icld_IconList);
1824 NewList((struct List*)&data->icld_SelectionList);
1826 data->icld_IconLabelFont = icl_WindowFont;
1828 /* Setup Icon View-Mode options */
1829 data->icld_IVMAttribs = AllocMem(sizeof(struct IconViewModeAttribs), MEMF_CLEAR);
1830 /* Setup List View-Mode options */
1831 if ((data->icld_LVMAttribs = AllocMem(sizeof(struct ListViewModeAttribs), MEMF_CLEAR)) != NULL)
1833 for(i = 0; i < NUM_COLUMNS; i++)
1835 data->icld_LVMAttribs->lmva_ColumnPos[i] = i;
1836 data->icld_LVMAttribs->lmva_ColumnFlags[i] = LVMCF_COLVISIBLE;
1837 data->icld_LVMAttribs->lmva_ColumnWidth[i] = 100;
1838 data->icld_LVMAttribs->lmva_ColumnAlign[i] = COLUMN_ALIGN_LEFT;
1839 switch (i)
1841 case INDEX_NAME:
1842 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= (LVMCF_COLCLICKABLE|LVMCF_COLSORTABLE);
1843 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Name";
1844 break;
1846 case INDEX_SIZE:
1847 data->icld_LVMAttribs->lmva_ColumnAlign[i] = COLUMN_ALIGN_RIGHT;
1848 data->icld_LVMAttribs->lmva_ColumnFlags[i] | LVMCF_COLSORTABLE;
1849 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Size";
1850 break;
1852 case INDEX_DATE:
1853 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= LVMCF_COLSORTABLE;
1854 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Date";
1855 break;
1857 case INDEX_TIME:
1858 data->icld_LVMAttribs->lmva_ColumnFlags[i] |= LVMCF_COLSORTABLE;
1859 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Time";
1860 break;
1862 case INDEX_COMMENT:
1863 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Comment";
1864 break;
1866 case INDEX_PROTECTION:
1867 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "Protection";
1868 break;
1870 default:
1871 data->icld_LVMAttribs->lmva_ColumnTitle[i] = "<Unknown>";
1872 break;
1875 data->icld_LVMAttribs->lmva_LastSelectedColumn = -1;
1876 data->icld_LVMAttribs->lmva_SortColumn = INDEX_NAME;
1877 data->icld_LVMAttribs->lmva_HeaderHeight = HEADERLINE_EXTRAHEIGHT + data->icld_IconLabelFont->tf_YSize;
1878 data->icld_LVMAttribs->lmva_RowHeight = LINE_EXTRAHEIGHT + data->icld_IconLabelFont->tf_YSize;
1879 data->icld_LVMAttribs->lvma_Flags = LVMAF_HEADERDRAWTOEND;
1882 /* Get/Set initial values */
1883 #warning "TODO: TrimVolumeNames should be prefs settable"
1884 data->icld__Option_TrimVolumeNames = TRUE;
1885 #warning "TODO: Adjust overlap by window border width"
1886 data->icld__Option_IconBorderOverlap = 10;
1888 data->icld__Option_IconListMode = (UBYTE)GetTagData(MUIA_IconList_IconListMode, 0, message->ops_AttrList);
1889 data->icld__Option_LabelTextMode = (UBYTE)GetTagData(MUIA_IconList_LabelText_Mode, 0, message->ops_AttrList);
1890 data->icld__Option_LabelTextMaxLen = (ULONG)GetTagData(MUIA_IconList_LabelText_MaxLineLen, ILC_ICONLABEL_MAXLINELEN_DEFAULT, message->ops_AttrList);
1892 if ( data->icld__Option_LabelTextMaxLen < ILC_ICONLABEL_SHORTEST )
1893 data->icld__Option_LabelTextMaxLen = ILC_ICONLABEL_MAXLINELEN_DEFAULT;
1895 data->icld__Option_LastLabelTextMaxLen = data->icld__Option_LabelTextMaxLen;
1897 #if defined(DEBUG_ILC_FUNCS)
1898 D(bug("[IconList] %s: MaxLineLen : %ld\n", __PRETTY_FUNCTION__, data->icld__Option_LabelTextMaxLen));
1899 #endif
1900 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_NEWSIZE;
1901 data->ehn.ehn_Priority = 0;
1902 data->ehn.ehn_Flags = 0;
1903 data->ehn.ehn_Object = obj;
1904 data->ehn.ehn_Class = CLASS;
1906 data->icld_SortFlags = MUIV_IconList_Sort_ByName;
1907 data->icld_DisplayFlags = ICONLIST_DISP_SHOWINFO;
1909 __iconlist_UpdateLabels_hook.h_Entry = (HOOKFUNC)IconList__HookFunc_UpdateLabelsFunc;
1911 DoMethod
1913 obj, MUIM_Notify, MUIA_IconList_LabelText_MaxLineLen, MUIV_EveryTime,
1914 (IPTR)obj, 3,
1915 MUIM_CallHook, &__iconlist_UpdateLabels_hook, (IPTR)CLASS
1918 DoMethod
1920 obj, MUIM_Notify, MUIA_IconList_LabelText_MultiLine, MUIV_EveryTime,
1921 (IPTR)obj, 3,
1922 MUIM_CallHook, &__iconlist_UpdateLabels_hook, (IPTR)CLASS
1925 #if defined(DEBUG_ILC_FUNCS)
1926 D(bug("[IconList] obj = %ld\n", obj));
1927 #endif
1928 return (IPTR)obj;
1932 ///OM_DISPOSE()
1933 /**************************************************************************
1934 OM_DISPOSE
1935 **************************************************************************/
1936 IPTR IconList__OM_DISPOSE(struct IClass *CLASS, Object *obj, Msg message)
1938 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1939 struct IconEntry *node = NULL;
1941 #if defined(DEBUG_ILC_FUNCS)
1942 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1943 #endif
1945 #if defined(__AROS__)
1946 ForeachNode(&data->icld_IconList, node)
1947 #else
1948 Foreach_Node(&data->icld_IconList, node);
1949 #endif
1951 if (node->ie_DiskObj)
1952 FreeDiskObject(node->ie_DiskObj);
1955 if (data->icld_Pool) DeletePool(data->icld_Pool);
1957 DoSuperMethodA(CLASS,obj,message);
1958 return (IPTR)NULL;
1962 ///OM_SET()
1963 /**************************************************************************
1964 OM_SET
1965 **************************************************************************/
1966 IPTR IconList__OM_SET(struct IClass *CLASS, Object *obj, struct opSet *message)
1968 struct IconList_DATA *data = INST_DATA(CLASS, obj);
1969 struct TagItem *tag = NULL,
1970 *tags = NULL;
1972 WORD oldleft = data->icld_ViewX,
1973 oldtop = data->icld_ViewY;
1974 //oldwidth = data->icld_ViewWidth,
1975 //oldheight = data->icld_ViewHeight;
1977 #if defined(DEBUG_ILC_FUNCS) && defined(DEBUG_ILC_ATTRIBS)
1978 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
1979 #endif
1981 /* parse initial taglist */
1982 for (tags = message->ops_AttrList; (tag = NextTagItem((TAGITEM)&tags)); )
1984 switch (tag->ti_Tag)
1986 case MUIA_Virtgroup_Left:
1987 #if defined(DEBUG_ILC_ATTRIBS)
1988 D(bug("[IconList] %s: MUIA_Virtgroup_Left %ld\n", __PRETTY_FUNCTION__, tag->ti_Data));
1989 #endif
1990 if (data->icld_ViewX != tag->ti_Data)
1991 data->icld_ViewX = tag->ti_Data;
1992 break;
1994 case MUIA_Virtgroup_Top:
1995 #if defined(DEBUG_ILC_ATTRIBS)
1996 D(bug("[IconList] %s: MUIA_Virtgroup_Top %ld\n", __PRETTY_FUNCTION__, tag->ti_Data));
1997 #endif
1998 if (data->icld_ViewY != tag->ti_Data)
1999 data->icld_ViewY = tag->ti_Data;
2000 break;
2002 case MUIA_IconList_Rastport:
2003 #if defined(DEBUG_ILC_ATTRIBS)
2004 D(bug("[IconList] %s: MUIA_IconList_Rastport 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2005 #endif
2006 data->icld_DisplayRastPort = (struct RastPort*)tag->ti_Data;
2007 data->icld_DrawOffsetX = _mleft(obj);
2008 data->icld_DrawOffsetY = _mtop(obj);
2009 if (data->icld_BufferRastPort != NULL)
2011 //Buffer still set!?!?!
2013 SET(obj, MUIA_IconList_BufferRastport, tag->ti_Data);
2014 break;
2016 case MUIA_IconList_BufferRastport:
2017 #if defined(DEBUG_ILC_ATTRIBS)
2018 D(bug("[IconList] %s: MUIA_IconList_BufferRastport 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2019 #endif
2020 data->icld_BufferRastPort = (struct RastPort*)tag->ti_Data;
2021 break;
2023 case MUIA_Font:
2024 #if defined(DEBUG_ILC_ATTRIBS)
2025 D(bug("[IconList] %s: MUIA_Font 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2026 #endif
2027 data->icld_IconLabelFont = (struct TextFont*)tag->ti_Data;
2028 break;
2030 case MUIA_IconList_LabelInfoText_Font:
2031 #if defined(DEBUG_ILC_ATTRIBS)
2032 D(bug("[IconList] %s: MUIA_IconList_LabelInfoText_Font 0x%p\n", __PRETTY_FUNCTION__, tag->ti_Data));
2033 #endif
2034 data->icld_IconInfoFont = (struct TextFont*)tag->ti_Data;
2035 break;
2037 case MUIA_IconList_DisplayFlags:
2039 #if defined(DEBUG_ILC_ATTRIBS)
2040 D(bug("[IconList] %s: MUIA_IconList_DisplayFlags %08x\n", __PRETTY_FUNCTION__, tag->ti_Data));
2041 #endif
2042 ULONG origModeFlags = data->icld_DisplayFlags & (ICONLIST_DISP_MODEDEFAULT|ICONLIST_DISP_MODELABELRIGHT|ICONLIST_DISP_MODELIST);
2043 data->icld_DisplayFlags = (ULONG)tag->ti_Data;
2045 if (data->icld_DisplayFlags & ICONLIST_DISP_BUFFERED)
2047 struct BitMap *bitmap_New = NULL;
2048 ULONG tmp_RastDepth;
2050 #if defined(DEBUG_ILC_ATTRIBS) && defined(DEBUG_ILC_ICONRENDERING)
2051 D(bug("[IconList] %s: MUIA_IconList_DisplayFlags & ICONLIST_DISP_BUFFERED\n", __PRETTY_FUNCTION__));
2052 #endif
2053 if ((data->icld_BufferRastPort != NULL)
2054 && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
2056 #if defined(DEBUG_ILC_ATTRIBS) && defined(DEBUG_ILC_ICONRENDERING)
2057 D(bug("[IconList] %s: BackLayer @ %p for BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
2058 #endif
2059 if ((GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_WIDTH) != data->icld_ViewWidth)
2060 || (GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_HEIGHT) != data->icld_ViewHeight))
2062 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
2063 #if defined(DEBUG_ILC_ATTRIBS) && defined(DEBUG_ILC_ICONRENDERING)
2064 D(bug("[IconList] %s: Destroying old BackLayer\n", __PRETTY_FUNCTION__));
2065 #endif
2066 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2067 DeleteLayer(0, oldLayer);
2071 if ((data->icld_BufferRastPort == NULL) || (data->icld_BufferRastPort == data->icld_DisplayRastPort))
2073 tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
2074 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
2075 data->icld_ViewHeight,
2076 tmp_RastDepth,
2077 BMF_CLEAR,
2078 data->icld_DisplayRastPort->BitMap))!=NULL)
2082 struct Layer * buffLayer = CreateLayerTagList(&_screen(obj)->LayerInfo,
2083 bitmap_New,
2086 data->icld_ViewWidth,
2087 data->icld_ViewHeight,
2088 LAYERSIMPLE,
2089 __iconList_BackBuffLayerTags);
2091 if (buffLayer != NULL)
2093 data->icld_BufferRastPort = buffLayer->rp;
2094 #if defined(DEBUG_ILC_ATTRIBS) && defined(DEBUG_ILC_ICONRENDERING)
2095 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
2096 #endif
2097 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
2098 data->icld_DrawOffsetX = 0;
2099 data->icld_DrawOffsetY = 0;
2101 else
2103 FreeBitMap(bitmap_New);
2104 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2105 data->icld_DrawOffsetX = _mleft(obj);
2106 data->icld_DrawOffsetY = _mtop(obj);
2111 else
2113 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
2115 //Free up the buffers layer, rastport and bitmap since they are no longer needed ..
2116 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
2117 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2118 DeleteLayer(0, oldLayer);
2119 data->icld_DrawOffsetX = _mleft(obj);
2120 data->icld_DrawOffsetY = _mtop(obj);
2123 SET(obj, MUIA_IconList_Changed, TRUE);
2125 break;
2127 case MUIA_IconList_SortFlags:
2128 #if defined(DEBUG_ILC_ATTRIBS)
2129 D(bug("[IconList] %s: MUIA_IconList_SortFlags %08x\n", __PRETTY_FUNCTION__, tag->ti_Data));
2130 #endif
2131 data->icld_SortFlags = (ULONG)tag->ti_Data;
2132 break;
2134 case MUIA_IconList_IconListMode:
2135 #if defined(DEBUG_ILC_ATTRIBS)
2136 D(bug("[IconList] %s: MUIA_IconList_IconListMode %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2137 #endif
2138 data->icld__Option_IconListMode = (UBYTE)tag->ti_Data;
2139 break;
2141 case MUIA_IconList_LabelText_Mode:
2142 #if defined(DEBUG_ILC_ATTRIBS)
2143 D(bug("[IconList] %s: MUIA_IconList_LabelText_Mode %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2144 #endif
2145 data->icld__Option_LabelTextMode = (UBYTE)tag->ti_Data;
2146 break;
2148 case MUIA_IconList_LabelText_MaxLineLen:
2149 #if defined(DEBUG_ILC_ATTRIBS)
2150 D(bug("[IconList] %s: MUIA_IconList_LabelText_MaxLineLen %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2151 #endif
2152 if (tag->ti_Data >= ILC_ICONLABEL_SHORTEST)
2154 data->icld__Option_LabelTextMaxLen = (ULONG)tag->ti_Data;
2156 else
2158 data->icld__Option_LabelTextMaxLen = ILC_ICONLABEL_MAXLINELEN_DEFAULT;
2160 break;
2162 case MUIA_IconList_LabelText_MultiLine:
2163 #if defined(DEBUG_ILC_ATTRIBS)
2164 D(bug("[IconList] %s: MUIA_IconList_LabelText_MultiLine %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2165 #endif
2166 data->icld__Option_LabelTextMultiLine = (ULONG)tag->ti_Data;
2167 if (data->icld__Option_LabelTextMultiLine == 0)data->icld__Option_LabelTextMultiLine = 1;
2168 break;
2170 case MUIA_IconList_LabelText_MultiLineOnFocus:
2171 #if defined(DEBUG_ILC_ATTRIBS)
2172 D(bug("[IconList] %s: MUIA_IconList_LabelText_MultiLineOnFocus %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2173 #endif
2174 data->icld__Option_LabelTextMultiLineOnFocus = (BOOL)tag->ti_Data;
2175 break;
2177 case MUIA_IconList_Icon_HorizontalSpacing:
2178 #if defined(DEBUG_ILC_ATTRIBS)
2179 D(bug("[IconList] %s: MUIA_IconList_Icon_HorizontalSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2180 #endif
2181 data->icld__Option_IconHorizontalSpacing = (UBYTE)tag->ti_Data;
2182 break;
2184 case MUIA_IconList_Icon_VerticalSpacing:
2185 #if defined(DEBUG_ILC_ATTRIBS)
2186 D(bug("[IconList] %s: MUIA_IconList_Icon_VerticalSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2187 #endif
2188 data->icld__Option_IconVerticalSpacing = (UBYTE)tag->ti_Data;
2189 break;
2191 case MUIA_IconList_Icon_ImageSpacing:
2192 #if defined(DEBUG_ILC_ATTRIBS)
2193 D(bug("[IconList] %s: MUIA_IconList_Icon_ImageSpacing %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2194 #endif
2195 data->icld__Option_IconImageSpacing = (UBYTE)tag->ti_Data;
2196 break;
2198 case MUIA_IconList_LabelText_HorizontalPadding:
2199 #if defined(DEBUG_ILC_ATTRIBS)
2200 D(bug("[IconList] %s: MUIA_IconList_LabelText_HorizontalPadding %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2201 #endif
2202 data->icld__Option_LabelTextHorizontalPadding = (UBYTE)tag->ti_Data;
2203 break;
2205 case MUIA_IconList_LabelText_VerticalPadding:
2206 #if defined(DEBUG_ILC_ATTRIBS)
2207 D(bug("[IconList] %s: MUIA_IconList_LabelText_VerticalPadding %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2208 #endif
2209 data->icld__Option_LabelTextVerticalPadding = (UBYTE)tag->ti_Data;
2210 break;
2212 case MUIA_IconList_LabelText_BorderWidth:
2213 #if defined(DEBUG_ILC_ATTRIBS)
2214 D(bug("[IconList] %s: MUIA_IconList_LabelText_BorderWidth %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2215 #endif
2216 data->icld__Option_LabelTextBorderWidth = (UBYTE)tag->ti_Data;
2217 break;
2219 case MUIA_IconList_LabelText_BorderHeight:
2220 #if defined(DEBUG_ILC_ATTRIBS)
2221 D(bug("[IconList] %s: MUIA_IconList_LabelText_BorderHeight %d\n", __PRETTY_FUNCTION__, tag->ti_Data));
2222 #endif
2223 data->icld__Option_LabelTextBorderHeight = (UBYTE)tag->ti_Data;
2224 break;
2226 case MUIA_IconList_LabelText_Pen:
2227 data->icld_LabelPen = (ULONG)tag->ti_Data;
2228 break;
2230 case MUIA_IconList_LabelText_ShadowPen:
2231 data->icld_LabelShadowPen = (ULONG)tag->ti_Data;
2232 break;
2234 case MUIA_IconList_LabelInfoText_Pen:
2235 data->icld_InfoPen = (ULONG)tag->ti_Data;
2236 break;
2238 case MUIA_IconList_LabelInfoText_ShadowPen:
2239 data->icld_InfoShadowPen = (ULONG)tag->ti_Data;
2240 break;
2242 /* Settings defined by the view class */
2243 case MUIA_IconListview_FixedBackground:
2244 #if defined(DEBUG_ILC_ATTRIBS)
2245 D(bug("[IconList] %s: MUIA_IconListview_FixedBackground\n", __PRETTY_FUNCTION__));
2246 #endif
2247 data->icld__Option_IconListFixedBackground = (BOOL)tag->ti_Data;
2248 break;
2250 case MUIA_IconListview_ScaledBackground:
2251 #if defined(DEBUG_ILC_ATTRIBS)
2252 D(bug("[IconList] %s: MUIA_IconListview_ScaledBackground\n", __PRETTY_FUNCTION__));
2253 #endif
2254 data->icld__Option_IconListScaledBackground = (BOOL)tag->ti_Data;
2255 break;
2257 /* We listen for MUIA_Background and set default values for known types */
2258 case MUIA_Background:
2259 #if defined(DEBUG_ILC_ATTRIBS) && defined(DEBUG_ILC_ICONRENDERING)
2260 D(bug("[IconList] %s: MUIA_Background\n", __PRETTY_FUNCTION__));
2261 #endif
2263 char *bgmode_string = (char *)tag->ti_Data;
2264 BYTE this_mode = bgmode_string[0] - 48;
2266 #if defined(DEBUG_ILC_ATTRIBS) && defined(DEBUG_ILC_ICONRENDERING)
2267 D(bug("[IconList] %s: MUIA_Background | MUI BG Mode = %d\n", __PRETTY_FUNCTION__, this_mode));
2268 #endif
2269 switch (this_mode)
2271 case 0:
2272 //MUI Pattern
2273 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2274 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2275 break;
2276 case 2:
2277 //MUI RGB color
2278 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2279 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2280 break;
2281 case 7:
2282 //Zune Gradient
2283 NNSET(obj, MUIA_IconListview_FixedBackground, TRUE);
2284 NNSET(obj, MUIA_IconListview_ScaledBackground, TRUE);
2285 break;
2286 case 5:
2287 //Image
2288 NNSET(obj, MUIA_IconListview_FixedBackground, FALSE);
2289 NNSET(obj, MUIA_IconListview_ScaledBackground, FALSE);
2290 break;
2293 break;
2294 case MUIA_IconList_IconsDropped:
2295 data->icld_DragDropEvent = (struct IconList_Drop_Event *)tag->ti_Data;
2296 break;
2300 #if defined(DEBUG_ILC_ATTRIBS)
2301 D(bug("[IconList] %s(), out of switch\n", __PRETTY_FUNCTION__));
2302 #endif
2303 if ((oldleft != data->icld_ViewX) || (oldtop != data->icld_ViewY))
2305 data->icld_UpdateMode = UPDATE_SCROLL;
2306 data->update_scrolldx = data->icld_ViewX - oldleft;
2307 data->update_scrolldy = data->icld_ViewY - oldtop;
2308 #if defined(DEBUG_ILC_ATTRIBS)
2309 D(bug("[IconList] %s(), call MUI_Redraw()\n", __PRETTY_FUNCTION__));
2310 #endif
2311 MUI_Redraw(obj, MADF_DRAWUPDATE);
2314 #if defined(DEBUG_ILC_ATTRIBS)
2315 D(bug("[IconList] %s(), call DoSuperMethodA()\n", __PRETTY_FUNCTION__));
2316 #endif
2317 return DoSuperMethodA(CLASS, obj, (Msg)message);
2321 ///OM_GET()
2322 /**************************************************************************
2323 OM_GET
2324 **************************************************************************/
2325 IPTR IconList__OM_GET(struct IClass *CLASS, Object *obj, struct opGet *message)
2327 /* small macro to simplify return value storage */
2328 #define STORE *(message->opg_Storage)
2329 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2331 #if defined(DEBUG_ILC_FUNCS) && defined(DEBUG_ILC_ATTRIBS)
2332 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2333 #endif
2335 switch (message->opg_AttrID)
2337 case MUIA_IconList_Rastport: STORE = (IPTR)data->icld_DisplayRastPort; return 1;
2338 case MUIA_IconList_BufferRastport: STORE = (IPTR)data->icld_BufferRastPort; return 1;
2339 case MUIA_IconList_BufferLeft: STORE = (IPTR)data->icld_DrawOffsetX; return 1;
2340 case MUIA_IconList_BufferTop: STORE = (IPTR)data->icld_DrawOffsetY; return 1;
2341 case MUIA_IconList_BufferWidth:
2342 case MUIA_IconList_Width: STORE = (IPTR)data->icld_AreaWidth; return 1;
2343 case MUIA_IconList_BufferHeight:
2344 case MUIA_IconList_Height: STORE = (IPTR)data->icld_AreaHeight; return 1;
2345 case MUIA_IconList_IconsDropped: STORE = (IPTR)data->icld_DragDropEvent; return 1;
2346 case MUIA_IconList_Clicked: STORE = (IPTR)&data->icld_ClickEvent; return 1;
2347 case MUIA_IconList_IconListMode: STORE = (IPTR)data->icld__Option_IconListMode; return 1;
2348 case MUIA_IconList_LabelText_Mode: STORE = (IPTR)data->icld__Option_LabelTextMode; return 1;
2349 case MUIA_IconList_LabelText_MaxLineLen: STORE = (IPTR)data->icld__Option_LabelTextMaxLen; return 1;
2350 case MUIA_IconList_LabelText_MultiLine: STORE = (IPTR)data->icld__Option_LabelTextMultiLine; return 1;
2351 case MUIA_IconList_LabelText_MultiLineOnFocus: STORE = (IPTR)data->icld__Option_LabelTextMultiLineOnFocus; return 1;
2352 case MUIA_IconList_DisplayFlags: STORE = (IPTR)data->icld_DisplayFlags; return 1;
2353 case MUIA_IconList_SortFlags: STORE = (IPTR)data->icld_SortFlags; return 1;
2355 case MUIA_IconList_FocusIcon: STORE = (IPTR)data->icld_FocusIcon; return 1;
2357 case MUIA_Font: STORE = (IPTR)data->icld_IconLabelFont; return 1;
2358 case MUIA_IconList_LabelText_Pen: STORE = (IPTR)data->icld_LabelPen; return 1;
2359 case MUIA_IconList_LabelText_ShadowPen: STORE = (IPTR)data->icld_LabelShadowPen; return 1;
2360 case MUIA_IconList_LabelInfoText_Font: STORE = (IPTR)data->icld_IconInfoFont; return 1;
2361 case MUIA_IconList_LabelInfoText_Pen: STORE = (IPTR)data->icld_InfoPen; return 1;
2362 case MUIA_IconList_LabelInfoText_ShadowPen: STORE = (IPTR)data->icld_InfoShadowPen; return 1;
2364 case MUIA_IconList_Icon_HorizontalSpacing: STORE = (IPTR)data->icld__Option_IconHorizontalSpacing; return 1;
2365 case MUIA_IconList_Icon_VerticalSpacing: STORE = (IPTR)data->icld__Option_IconVerticalSpacing; return 1;
2366 case MUIA_IconList_Icon_ImageSpacing: STORE = (IPTR)data->icld__Option_IconImageSpacing; return 1;
2367 case MUIA_IconList_LabelText_HorizontalPadding: STORE = (IPTR)data->icld__Option_LabelTextHorizontalPadding; return 1;
2368 case MUIA_IconList_LabelText_VerticalPadding: STORE = (IPTR)data->icld__Option_LabelTextVerticalPadding; return 1;
2369 case MUIA_IconList_LabelText_BorderWidth: STORE = (IPTR)data->icld__Option_LabelTextBorderWidth; return 1;
2370 case MUIA_IconList_LabelText_BorderHeight: STORE = (IPTR)data->icld__Option_LabelTextBorderHeight; return 1;
2372 /* Settings defined by the view class */
2373 case MUIA_IconListview_FixedBackground: STORE = (IPTR)data->icld__Option_IconListFixedBackground; return 1;
2374 case MUIA_IconListview_ScaledBackground: STORE = (IPTR)data->icld__Option_IconListScaledBackground; return 1;
2376 /* ICON obj Changes */
2377 case MUIA_Virtgroup_Left: STORE = (IPTR)data->icld_ViewX; return 1;
2378 case MUIA_Virtgroup_Top: STORE = (IPTR)data->icld_ViewY; return 1;
2379 case MUIA_Family_List: STORE = (IPTR)&(data->icld_IconList); return 1; /* Get our list object */
2381 #warning "TODO: Get the version/revision from our config.."
2382 case MUIA_Version: STORE = (IPTR)1; return 1;
2383 case MUIA_Revision: STORE = (IPTR)7; return 1;
2386 return DoSuperMethodA(CLASS, obj, (Msg) message);
2387 #undef STORE
2391 IPTR IconList__MUIM_Family_AddHead(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddHead *message)
2393 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2394 #if defined(DEBUG_ILC_FUNCS)
2395 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2396 #endif
2398 if (message->obj)
2400 #warning "TODO: Use the correct _OBJECT() code when we switch to icon.mui"
2401 // AddHead(&(data->icld_IconList), (struct Node *)_OBJECT(message->obj));
2402 AddHead(&(data->icld_IconList), (struct Node *)message->obj);
2403 return TRUE;
2405 else
2406 return FALSE;
2409 IPTR IconList__MUIM_Family_AddTail(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddTail *message)
2411 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2412 #if defined(DEBUG_ILC_FUNCS)
2413 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2414 #endif
2416 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));
2418 if (message->obj)
2420 #warning "TODO: Use the correct _OBJECT() code when we switch to icon.mui"
2421 // AddTail(&(data->icld_IconList), (struct Node *)_OBJECT(message->obj));
2422 AddTail(&(data->icld_IconList), (struct Node *)message->obj);
2423 return TRUE;
2425 else
2426 return FALSE;
2428 return (IPTR)NULL;
2430 #if !defined(WANDERER_BUILTIN_ICONLIST)
2431 IPTR IconList__OM_ADDMEMBER(struct IClass *CLASS, Object *obj, struct MUIP_Family_AddTail *message)
2433 return IconList__MUIM_Family_AddTail(CLASS, obj, message);
2435 #endif
2437 IPTR IconList__MUIM_Family_Remove(struct IClass *CLASS, Object *obj, struct MUIP_Family_Remove *message)
2439 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2440 #if defined(DEBUG_ILC_FUNCS)
2441 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2442 #endif
2444 D(bug("[IconList] %s: entry @ 0x%p '%s'\n", __PRETTY_FUNCTION__, message->obj, ((struct IconEntry *)message->obj)->ie_IconNode.ln_Name));
2446 if (message->obj)
2448 #warning "TODO: Use the correct _OBJECT() code when we switch to icon.mui"
2449 // Remove((struct Node *)_OBJECT(message->obj));
2450 Remove((struct Node *)message->obj);
2451 return TRUE;
2453 else
2454 return FALSE;
2456 return (IPTR)NULL;
2458 #if !defined(WANDERER_BUILTIN_ICONLIST)
2459 IPTR IconList__OM_REMMEMBER(struct IClass *CLASS, Object *obj, struct MUIP_Family_Remove *message)
2461 return IconList__MUIM_Family_Remove(CLASS, obj, message);
2463 #endif
2465 ///MUIM_Setup()
2466 /**************************************************************************
2467 MUIM_Setup
2468 **************************************************************************/
2469 IPTR IconList__MUIM_Setup(struct IClass *CLASS, Object *obj, struct MUIP_Setup *message)
2471 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2472 struct IconEntry *node = NULL;
2473 IPTR geticon_error = 0;
2475 #if defined(DEBUG_ILC_FUNCS)
2476 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2477 #endif
2479 if (!DoSuperMethodA(CLASS, obj, (Msg) message)) return (IPTR)NULL;
2481 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
2483 /* Get Internal Objects to use if not set .. */
2484 data->icld_DisplayRastPort = NULL;
2485 data->icld_BufferRastPort = NULL;
2487 if (data->icld_IconLabelFont == NULL) data->icld_IconLabelFont = _font(obj);
2488 if (data->icld_IconInfoFont == NULL) data->icld_IconInfoFont = data->icld_IconLabelFont;
2489 #if defined(DEBUG_ILC_ICONRENDERING)
2490 D(bug("[IconList] %s: Use Font @ 0x%p, RastPort @ 0x%p\n", __PRETTY_FUNCTION__, data->icld_IconLabelFont, data->icld_BufferRastPort ));
2491 #endif
2493 /* Set our base options .. */
2494 data->icld_LabelPen = _pens(obj)[MPEN_SHINE];
2495 data->icld_LabelShadowPen = _pens(obj)[MPEN_SHADOW];
2496 data->icld_InfoPen = _pens(obj)[MPEN_SHINE];
2497 data->icld_InfoShadowPen = _pens(obj)[MPEN_SHADOW];
2499 data->icld__Option_LabelTextMultiLine = 1;
2500 data->icld__Option_LastLabelTextMultiLine = data->icld__Option_LabelTextMultiLine;
2502 data->icld__Option_LabelTextMultiLineOnFocus = FALSE;
2504 data->icld__Option_IconHorizontalSpacing = ILC_ICON_HORIZONTALMARGIN_DEFAULT;
2505 data->icld__Option_IconVerticalSpacing = ILC_ICON_VERTICALMARGIN_DEFAULT;
2506 data->icld__Option_IconImageSpacing = ILC_ICONLABEL_IMAGEMARGIN_DEFAULT;
2507 data->icld__Option_LabelTextHorizontalPadding = ILC_ICONLABEL_HORIZONTALTEXTMARGIN_DEFAULT;
2508 data->icld__Option_LabelTextVerticalPadding = ILC_ICONLABEL_VERTICALTEXTMARGIN_DEFAULT;
2509 data->icld__Option_LabelTextBorderWidth = ILC_ICONLABEL_BORDERWIDTH_DEFAULT;
2510 data->icld__Option_LabelTextBorderHeight = ILC_ICONLABEL_BORDERHEIGHT_DEFAULT;
2512 #if defined(__AROS__)
2513 ForeachNode(&data->icld_IconList, node)
2514 #else
2515 Foreach_Node(&data->icld_IconList, node);
2516 #endif
2518 if (!node->ie_DiskObj)
2520 IPTR iconlistScreen = _screen(obj);
2521 #if defined(DEBUG_ILC_ICONRENDERING)
2522 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
2523 #endif
2524 if (!(node->ie_DiskObj = GetIconTags(node->ie_IconNode.ln_Name,
2525 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
2526 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
2527 ICONGETA_GenerateImageMasks, TRUE,
2528 ICONGETA_FailIfUnavailable, FALSE,
2529 ICONA_ErrorCode, &geticon_error,
2530 TAG_DONE)))
2532 #if defined(DEBUG_ILC_ICONRENDERING)
2533 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));
2534 #endif
2535 /* We should probably remove this node if the entry cant be obtained ? */
2539 return 1;
2543 ///MUIM_Show()
2544 /**************************************************************************
2545 MUIM_Show
2546 **************************************************************************/
2547 IPTR IconList__MUIM_Show(struct IClass *CLASS, Object *obj, struct MUIP_Show *message)
2549 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2550 LONG newleft,
2551 newtop;
2552 IPTR rc;
2554 #if defined(DEBUG_ILC_FUNCS)
2555 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2556 #endif
2558 if ((rc = DoSuperMethodA(CLASS, obj, (Msg)message)))
2560 newleft = data->icld_ViewX;
2561 newtop = data->icld_ViewY;
2563 if (newleft + _mwidth(obj) > data->icld_AreaWidth)
2564 newleft = data->icld_AreaWidth - _mwidth(obj);
2565 if (newleft < 0)
2566 newleft = 0;
2568 if (newtop + _mheight(obj) > data->icld_AreaHeight)
2569 newtop = data->icld_AreaHeight - _mheight(obj);
2570 if (newtop < 0)
2571 newtop = 0;
2573 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
2575 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
2576 MUIA_Virtgroup_Top, newtop,
2577 TAG_DONE);
2580 /* Get Internal Objects to use if not set .. */
2581 if (data->icld_DisplayRastPort == NULL)
2583 if (_rp(obj) != NULL)
2585 data->icld_DisplayRastPort = CloneRastPort(_rp(obj));
2587 #if defined(DEBUG_ILC_ICONRENDERING)
2588 else
2590 D(bug("[IconList] IconList__MUIM_Show: ERROR - NULL RastPort!\n"));
2592 #endif
2595 if (data->icld_DisplayFlags & ICONLIST_DISP_BUFFERED)
2597 struct BitMap *bitmap_New = NULL;
2598 ULONG tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
2599 if ((bitmap_New = AllocBitMap(data->icld_ViewWidth,
2600 data->icld_ViewHeight,
2601 tmp_RastDepth,
2602 BMF_CLEAR,
2603 data->icld_DisplayRastPort->BitMap))!=NULL)
2605 struct Layer * buffLayer = CreateLayerTagList(&_screen(obj)->LayerInfo,
2606 bitmap_New,
2609 data->icld_ViewWidth,
2610 data->icld_ViewHeight,
2611 LAYERSIMPLE,
2612 __iconList_BackBuffLayerTags);
2614 if (buffLayer != NULL)
2616 data->icld_BufferRastPort = buffLayer->rp;
2617 #if defined(DEBUG_ILC_ATTRIBS) && defined(DEBUG_ILC_ICONRENDERING)
2618 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
2619 #endif
2620 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
2621 data->icld_DrawOffsetX = 0;
2622 data->icld_DrawOffsetY = 0;
2624 else
2626 FreeBitMap(bitmap_New);
2627 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2628 data->icld_DrawOffsetX = _mleft(obj);
2629 data->icld_DrawOffsetY = _mtop(obj);
2633 else
2635 data->icld_BufferRastPort = data->icld_DisplayRastPort;
2636 data->icld_DrawOffsetX = _mleft(obj);
2637 data->icld_DrawOffsetY = _mtop(obj);
2640 if (data->icld_IconLabelFont == NULL) data->icld_IconLabelFont = _font(obj);
2641 if (data->icld_IconInfoFont == NULL) data->icld_IconInfoFont = data->icld_IconLabelFont;
2642 #if defined(DEBUG_ILC_ICONRENDERING)
2643 D(bug("[IconList] IconList__MUIM_Show: Use Font @ 0x%p, RastPort @ 0x%p\n", data->icld_IconLabelFont, data->icld_BufferRastPort ));
2644 #endif
2646 if ((data->icld_BufferRastPort) && (data->icld_IconLabelFont))
2647 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
2649 return rc;
2653 ///MUIM_Hide()
2654 /**************************************************************************
2655 MUIM_Hide
2656 **************************************************************************/
2657 IPTR IconList__MUIM_Hide(struct IClass *CLASS, Object *obj, struct MUIP_Hide *message)
2659 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2660 IPTR rc;
2662 #if defined(DEBUG_ILC_FUNCS)
2663 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2664 #endif
2666 if ((rc = DoSuperMethodA(CLASS, obj, (Msg)message)))
2668 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
2670 DeleteLayer(0, data->icld_BufferRastPort->Layer);
2673 data->icld_BufferRastPort = NULL;
2675 if (data->icld_DisplayRastPort)
2676 FreeRastPort(data->icld_DisplayRastPort);
2678 data->icld_DisplayRastPort = NULL;
2680 return rc;
2684 ///MUIM_Cleanup()
2685 /**************************************************************************
2686 MUIM_Cleanup
2687 **************************************************************************/
2688 IPTR IconList__MUIM_Cleanup(struct IClass *CLASS, Object *obj, struct MUIP_Cleanup *message)
2690 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2691 struct IconEntry *node = NULL;
2693 #if defined(DEBUG_ILC_FUNCS)
2694 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2695 #endif
2697 #if defined(__AROS__)
2698 ForeachNode(&data->icld_IconList, node)
2699 #else
2700 Foreach_Node(&data->icld_IconList, node);
2701 #endif
2703 if (node->ie_DiskObj)
2705 FreeDiskObject(node->ie_DiskObj);
2706 node->ie_DiskObj = NULL;
2710 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
2712 return DoSuperMethodA(CLASS, obj, (Msg)message);
2716 ///MUIM_AskMinMax()
2717 /**************************************************************************
2718 MUIM_AskMinMax
2719 **************************************************************************/
2720 IPTR IconList__MUIM_AskMinMax(struct IClass *CLASS, Object *obj, struct MUIP_AskMinMax *message)
2722 ULONG rc = DoSuperMethodA(CLASS, obj, (Msg) message);
2724 #if defined(DEBUG_ILC_FUNCS)
2725 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2726 #endif
2728 message->MinMaxInfo->MinWidth += 96;
2729 message->MinMaxInfo->MinHeight += 64;
2731 message->MinMaxInfo->DefWidth += 200;
2732 message->MinMaxInfo->DefHeight += 180;
2734 message->MinMaxInfo->MaxWidth = MUI_MAXMAX;
2735 message->MinMaxInfo->MaxHeight = MUI_MAXMAX;
2737 return rc;
2741 ///MUIM_Layout()
2742 /**************************************************************************
2743 MUIM_Layout
2744 **************************************************************************/
2745 IPTR IconList__MUIM_Layout(struct IClass *CLASS, Object *obj,struct MUIP_Layout *message)
2747 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2748 ULONG rc;
2750 #if defined(DEBUG_ILC_FUNCS)
2751 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
2752 #endif
2754 rc = DoSuperMethodA(CLASS, obj, (Msg)message);
2756 data->icld_ViewWidth = _mwidth(obj);
2757 data->icld_ViewHeight = _mheight(obj);
2759 return rc;
2763 static LONG FirstVisibleLine(struct IconList_DATA *data)
2765 return data->icld_ViewY / data->icld_LVMAttribs->lmva_RowHeight;
2768 static LONG NumVisibleLines(struct IconList_DATA *data)
2770 LONG visible = data->icld_ViewHeight + data->icld_LVMAttribs->lmva_RowHeight - 1 +
2771 (data->icld_ViewY % data->icld_LVMAttribs->lmva_RowHeight);
2773 visible /= data->icld_LVMAttribs->lmva_RowHeight;
2775 return visible;
2778 static void RenderListViewModeHeaderField(Object *obj, struct IconList_DATA *data,
2779 struct Rectangle *rect, LONG index, BOOL sel)
2781 IPTR penFill, penText, penDark, penBright;
2782 STRPTR text;
2783 struct TextExtent te;
2784 ULONG fit;
2786 if (sel == TRUE)
2788 penFill = _pens(obj)[MPEN_HALFSHADOW];
2789 penBright = _pens(obj)[MPEN_SHADOW];
2790 penDark = _pens(obj)[MPEN_HALFSHINE];
2792 else
2794 penFill = _pens(obj)[MPEN_HALFSHINE];
2795 penBright = _pens(obj)[MPEN_SHINE];
2796 penDark = _pens(obj)[MPEN_HALFSHADOW];
2798 penText = _pens(obj)[MPEN_TEXT];
2800 #if defined(DEBUG_ILC_FUNCS)
2801 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
2802 #endif
2804 if (((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0) && (index < NUM_COLUMNS))
2806 text = data->icld_LVMAttribs->lmva_ColumnTitle[index];
2808 SetAPen(data->icld_BufferRastPort, penFill); /* Background */
2809 RectFill(data->icld_BufferRastPort, rect->MinX + 1, rect->MinY + 1,
2810 rect->MaxX - 1, rect->MaxY - 1);
2812 SetAPen(data->icld_BufferRastPort, penBright); /* Top/Left */
2813 RectFill(data->icld_BufferRastPort, rect->MinX, rect->MinY, rect->MinX, rect->MaxY);
2814 RectFill(data->icld_BufferRastPort, rect->MinX + 1, rect->MinY, rect->MaxX - 1, rect->MinY);
2816 SetAPen(data->icld_BufferRastPort,penDark); /* Bottom/Right */
2817 RectFill(data->icld_BufferRastPort, rect->MaxX, rect->MinY, rect->MaxX, rect->MaxY);
2818 RectFill(data->icld_BufferRastPort, rect->MinX + 1, rect->MaxY, rect->MaxX - 1, rect->MaxY);
2820 /* Draw the Sort indicator .. */
2821 if (index == data->icld_LVMAttribs->lmva_SortColumn)
2823 LONG x = rect->MaxX - 4 - 6;
2824 LONG y = (rect->MinY + rect->MaxY + 1) / 2 - 3;
2826 if (x > rect->MinX)
2828 SetAPen(data->icld_BufferRastPort, _pens(obj)[sel ? MPEN_SHADOW : MPEN_HALFSHADOW]);
2829 if (data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
2831 RectFill(data->icld_BufferRastPort, x, y, x + 5, y + 1);
2832 RectFill(data->icld_BufferRastPort, x + 1, y + 2, x + 4, y + 3);
2833 RectFill(data->icld_BufferRastPort, x + 2, y + 4, x + 3, y + 5);
2835 else
2837 RectFill(data->icld_BufferRastPort, x, y + 4, x + 5, y + 5);
2838 RectFill(data->icld_BufferRastPort, x + 1, y + 2, x + 4, y + 3);
2839 RectFill(data->icld_BufferRastPort, x + 2, y, x + 3, y + 1);
2844 rect->MinX += HEADERENTRY_SPACING_LEFT;
2845 rect->MinY += HEADERLINE_SPACING_TOP;
2846 rect->MaxX -= HEADERENTRY_SPACING_RIGHT;
2847 rect->MaxY -= HEADERLINE_SPACING_BOTTOM;
2849 if (text && text[0])
2852 fit = TextFit(data->icld_BufferRastPort, text, strlen(text), &te, NULL, 1,
2853 rect->MaxX - rect->MinX + 1,
2854 rect->MaxY - rect->MinY + 1);
2856 if (!fit) return;
2858 SetABPenDrMd(data->icld_BufferRastPort, penText, 0, JAM1);
2859 Move(data->icld_BufferRastPort, rect->MinX, rect->MinY + data->icld_BufferRastPort->TxBaseline);
2860 Text(data->icld_BufferRastPort, text, fit);
2865 static void RenderListViewModeHeader(Object *obj, struct IconList_DATA *data)
2867 struct Rectangle linerect;
2868 LONG x, i;
2869 LONG firstvis, lastvis;
2871 #if defined(DEBUG_ILC_FUNCS)
2872 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
2873 #endif
2875 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0)
2877 linerect.MinX = _mleft(obj) - data->icld_ViewX;
2878 linerect.MaxX = _mright(obj);
2879 linerect.MinY = _mtop(obj);
2880 linerect.MaxY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight - 1;
2882 SetFont(data->icld_BufferRastPort, data->icld_IconLabelFont);
2884 x = linerect.MinX + HEADERLINE_SPACING_LEFT;
2886 firstvis = FirstVisibleColumnNumber(data);
2887 lastvis = LastVisibleColumnNumber(data);
2889 for(i = 0; i < NUM_COLUMNS; i++)
2891 LONG index = data->icld_LVMAttribs->lmva_ColumnPos[i];
2893 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
2895 BOOL outside = FALSE;
2896 struct Rectangle field_rect;
2898 field_rect.MinX = (i == firstvis) ? linerect.MinX : x;
2899 field_rect.MinY = linerect.MinY;
2900 field_rect.MaxX = x + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1 + ((i == lastvis) ? HEADERLINE_SPACING_RIGHT : 0);
2901 field_rect.MaxY = linerect.MaxY;
2903 /* data->update_rect1 and data->update_rect2 may
2904 point to rectangles to indicate that only icons
2905 in any of this rectangles need to be drawn */
2906 if (data->update_rect1)
2908 if (!RectAndRect(&field_rect, data->update_rect1))
2909 outside = TRUE;
2912 if (data->update_rect2)
2914 if (data->update_rect1)
2916 if ((outside == TRUE) && RectAndRect(&field_rect, data->update_rect2))
2917 outside = FALSE;
2919 else
2921 if (!RectAndRect(&field_rect, data->update_rect2))
2922 outside = TRUE;
2926 if (outside != TRUE)
2928 RenderListViewModeHeaderField(obj, data, &field_rect, index, FALSE);
2929 x += data->icld_LVMAttribs->lmva_ColumnWidth[index];
2931 else
2933 D(bug("[IconList] %s: Column '%s' outside of update area .. skipping\n", __PRETTY_FUNCTION__, data->icld_LVMAttribs->lmva_ColumnTitle[i]));
2937 if ((data->icld_LVMAttribs->lvma_Flags & LVMAF_HEADERDRAWTOEND) == LVMAF_HEADERDRAWTOEND)
2939 x += HEADERLINE_SPACING_RIGHT;
2941 if (x < linerect.MaxX)
2943 linerect.MinX = x;
2945 // if (MustRenderRect(data, &linerect))
2946 // {
2947 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_HALFSHINE], 0, JAM1);
2948 RectFill(data->icld_BufferRastPort, linerect.MinX, linerect.MinY, linerect.MaxX, linerect.MaxY);
2949 // }
2955 ///MUIM_Draw()
2956 /**************************************************************************
2957 MUIM_Draw - draw the IconList
2958 **************************************************************************/
2959 IPTR DrawCount;
2960 IPTR IconList__MUIM_Draw(struct IClass *CLASS, Object *obj, struct MUIP_Draw *message)
2962 struct IconList_DATA *data = INST_DATA(CLASS, obj);
2963 struct IconEntry *entry = NULL;
2965 APTR clip = NULL;
2967 ULONG update_oldwidth = 0,
2968 update_oldheight = 0;
2970 LONG clear_xoffset = 0,
2971 clear_yoffset = 0;
2973 IPTR draw_id = DrawCount++;
2975 #if defined(DEBUG_ILC_FUNCS)
2976 D(bug("[IconList]: %s(obj @ 0x%p)\n", __PRETTY_FUNCTION__, obj));
2977 #endif
2978 #if defined(DEBUG_ILC_ICONRENDERING)
2979 D(bug("[IconList] %s: id %d\n", __PRETTY_FUNCTION__, draw_id));
2980 #endif
2982 DoSuperMethodA(CLASS, obj, (Msg)message);
2984 if (!(data->icld__Option_IconListFixedBackground))
2986 clear_xoffset = data->icld_ViewX;
2987 clear_yoffset = data->icld_ViewY;
2990 // If window size changes, only update needed areas
2991 if (data->update_oldwidth == 0) data->update_oldwidth = data->icld_ViewWidth;
2992 if (data->update_oldheight == 0) data->update_oldheight = data->icld_ViewHeight;
2993 if ((data->update_oldwidth != data->icld_ViewWidth) || (data->update_oldheight != data->icld_ViewHeight))
2995 if (data->icld_UpdateMode != UPDATE_SCROLL)
2997 data->icld_UpdateMode = UPDATE_RESIZE;
2998 update_oldwidth = data->update_oldwidth;
2999 update_oldheight = data->update_oldheight;
3000 data->update_oldwidth = data->icld_ViewWidth;
3001 data->update_oldheight = data->icld_ViewHeight;
3005 if ((message->flags & MADF_DRAWUPDATE) || (data->icld_UpdateMode == UPDATE_RESIZE))
3007 #if defined(DEBUG_ILC_ICONRENDERING)
3009 if (message->flags & MADF_DRAWUPDATE)
3011 bug("[IconList] %s#%d: MADF_DRAWUPDATE\n", __PRETTY_FUNCTION__, draw_id);
3013 else
3015 bug("[IconList] %s#%d: UPDATE_RESIZE\n", __PRETTY_FUNCTION__, draw_id);
3018 #endif
3019 if ((data->icld_UpdateMode == UPDATE_HEADERENTRY) && (data->update_entry < NUM_COLUMNS)) /* draw the header entry */
3021 struct Rectangle field_rect;
3022 LONG index, i, firstvis, lastvis;
3024 firstvis = FirstVisibleColumnNumber(data);
3025 lastvis = LastVisibleColumnNumber(data);
3027 field_rect.MinX = _mleft(obj) - data->icld_ViewX;
3029 field_rect.MinY = _mtop(obj);
3030 field_rect.MaxY = field_rect.MinY + data->icld_LVMAttribs->lmva_HeaderHeight - 1;
3032 for(i = 0; i < NUM_COLUMNS; i++)
3034 index = data->icld_LVMAttribs->lmva_ColumnPos[i];
3035 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
3037 field_rect.MaxX = field_rect.MinX + data->icld_LVMAttribs->lmva_ColumnWidth[index] - 1;
3038 if (index == lastvis)
3039 field_rect.MaxX += HEADERLINE_SPACING_RIGHT;
3041 if (data->update_entry != index)
3043 field_rect.MinX += data->icld_LVMAttribs->lmva_ColumnWidth[index];
3044 if (index == firstvis)
3045 field_rect.MinX += HEADERLINE_SPACING_LEFT;
3047 else
3048 break;
3051 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mright(obj) - _mleft(obj) + 1, data->icld_LVMAttribs->lmva_HeaderHeight);
3053 if (data->icld_LVMAttribs->lmva_LastSelectedColumn == data->update_entry)
3054 RenderListViewModeHeaderField(obj, data, &field_rect, data->update_entry, TRUE);
3055 else
3056 RenderListViewModeHeaderField(obj, data, &field_rect, data->update_entry, FALSE);
3058 data->icld_UpdateMode = 0;
3059 data->update_entry = NULL;
3061 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3063 goto draw_done;
3065 else if ((data->icld_UpdateMode == UPDATE_SINGLEENTRY) && (data->update_entry != NULL)) /* draw only a single entry at update_entry */
3067 struct Rectangle rect;
3069 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3071 LONG count = 0, index = -1;
3073 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY + ICONLIST_DISP_MODELIST\n", __PRETTY_FUNCTION__, draw_id));
3075 rect.MinX = _mleft(obj);
3076 rect.MaxX = _mleft(obj) + _mwidth(obj) - 1;
3078 ForeachNode(&data->icld_IconList, entry)
3080 if (entry == data->update_entry)
3082 index = count;
3083 break;
3085 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
3087 count++;
3091 if (index != -1)
3093 rect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight - data->icld_ViewY + (index * data->icld_LVMAttribs->lmva_RowHeight);
3094 rect.MaxY = rect.MinY + data->icld_LVMAttribs->lmva_RowHeight - 1;
3096 if ((rect.MaxY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight))
3097 || (rect.MinY > (_mtop(obj) + _mheight(obj) - 1)))
3098 goto draw_done;
3100 if (rect.MinY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight)) rect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight;
3101 if (rect.MaxY > (_mtop(obj) + _mheight(obj) - 1)) rect.MaxY = _mtop(obj) + _mheight(obj) - 1;
3103 clip = MUI_AddClipping(muiRenderInfo(obj), rect.MinX, rect.MinY, rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1);
3105 DoMethod(obj, MUIM_DrawBackground,
3106 rect.MinX, rect.MinY,
3107 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3108 clear_xoffset, clear_yoffset,
3111 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3112 DoMethod(obj, MUIM_IconList_DrawEntry, data->update_entry, index);
3113 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3114 data->icld_UpdateMode = 0;
3115 data->update_entry = NULL;
3118 else
3120 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY (entry @ 0x%p)\n", __PRETTY_FUNCTION__, draw_id, data->update_entry));
3122 IconList_GetIconAreaRectangle(obj, data, data->update_entry, &rect);
3124 rect.MinX += _mleft(obj) + (data->update_entry->ie_IconX - data->icld_ViewX);
3125 rect.MaxX += _mleft(obj) + (data->update_entry->ie_IconX - data->icld_ViewX);
3126 rect.MinY += _mtop(obj) + (data->update_entry->ie_IconY - data->icld_ViewY);
3127 rect.MaxY += _mtop(obj) + (data->update_entry->ie_IconY - data->icld_ViewY);
3129 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
3131 if (data->update_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
3133 rect.MinX += ((data->icld_IconAreaLargestWidth - data->update_entry->ie_AreaWidth)/2);
3134 rect.MaxX += ((data->icld_IconAreaLargestWidth - data->update_entry->ie_AreaWidth)/2);
3137 if (data->update_entry->ie_AreaHeight < data->icld_IconAreaLargestHeight)
3139 rect.MinY += ((data->icld_IconAreaLargestHeight - data->update_entry->ie_AreaHeight)/2);
3140 rect.MaxY += ((data->icld_IconAreaLargestHeight - data->update_entry->ie_AreaHeight)/2);
3144 clip = MUI_AddClipping(muiRenderInfo(obj), rect.MinX, rect.MinY, rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1);
3146 #if defined(DEBUG_ILC_ICONRENDERING)
3147 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY: Calling MUIM_DrawBackground (A)\n", __PRETTY_FUNCTION__, draw_id));
3148 #endif
3149 DoMethod(obj, MUIM_DrawBackground,
3150 rect.MinX, rect.MinY,
3151 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3152 clear_xoffset, clear_yoffset,
3155 /* We could have deleted also other icons so they must be redrawn */
3156 #if defined(__AROS__)
3157 ForeachNode(&data->icld_IconList, entry)
3158 #else
3159 Foreach_Node(&data->icld_IconList, entry);
3160 #endif
3162 if ((entry != data->update_entry) && (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
3164 struct Rectangle rect2;
3165 IconList_GetIconAreaRectangle(obj, data, entry, &rect2);
3167 rect2.MinX += _mleft(obj) - data->icld_ViewX + entry->ie_IconX;
3168 rect2.MaxX += _mleft(obj) - data->icld_ViewX + entry->ie_IconX;
3169 rect2.MinY += _mtop(obj) - data->icld_ViewY + entry->ie_IconY;
3170 rect2.MaxY += _mtop(obj) - data->icld_ViewY + entry->ie_IconY;
3172 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
3174 if (entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
3176 rect2.MinX += ((data->icld_IconAreaLargestWidth - entry->ie_AreaWidth)/2);
3177 rect2.MaxX += ((data->icld_IconAreaLargestWidth - entry->ie_AreaWidth)/2);
3180 if (entry->ie_AreaHeight < data->icld_IconAreaLargestHeight)
3182 rect2.MinY += ((data->icld_IconAreaLargestHeight - entry->ie_AreaHeight)/2);
3183 rect2.MaxY += ((data->icld_IconAreaLargestHeight - entry->ie_AreaHeight)/2);
3187 if (RectAndRect(&rect, &rect2))
3189 // Update entry here
3190 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3191 DoMethod(obj, MUIM_IconList_DrawEntry, entry, ICONENTRY_DRAWMODE_PLAIN);
3192 DoMethod(obj, MUIM_IconList_DrawEntryLabel, entry, ICONENTRY_DRAWMODE_PLAIN);
3193 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3198 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3199 DoMethod(obj, MUIM_IconList_DrawEntry, data->update_entry, ICONENTRY_DRAWMODE_PLAIN);
3200 DoMethod(obj, MUIM_IconList_DrawEntryLabel, data->update_entry, ICONENTRY_DRAWMODE_PLAIN);
3201 entry->ie_Flags &= ~ICONENTRY_FLAG_NEEDSUPDATE;
3202 data->icld_UpdateMode = 0;
3203 data->update_entry = NULL;
3205 if (data->update_entry == NULL)
3207 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3209 #if defined(DEBUG_ILC_ICONRENDERING)
3210 D(bug("[IconList] %s#%d: UPDATE_SINGLEENTRY Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3211 #endif
3212 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3213 rect.MinX - _mleft(obj), rect.MinY - _mtop(obj),
3214 data->icld_DisplayRastPort,
3215 rect.MinX, rect.MinY,
3216 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
3217 0xC0);
3219 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3221 goto draw_done;
3223 else if (data->icld_UpdateMode == UPDATE_SCROLL)
3225 struct Region *region = NULL;
3226 struct Rectangle xrect,
3227 yrect;
3228 BOOL scroll_caused_damage;
3230 #if defined(DEBUG_ILC_ICONRENDERING)
3231 D(bug("[IconList] %s#%d: UPDATE_SCROLL.\n", __PRETTY_FUNCTION__, draw_id));
3232 #endif
3234 if (!data->icld__Option_IconListFixedBackground)
3236 scroll_caused_damage = (_rp(obj)->Layer->Flags & LAYERREFRESH) ? FALSE : TRUE;
3238 data->icld_UpdateMode = 0;
3240 if ((abs(data->update_scrolldx) >= _mwidth(obj)) ||
3241 (abs(data->update_scrolldy) >= _mheight(obj)))
3243 #if defined(DEBUG_ILC_ICONRENDERING)
3244 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Moved outside current view -> Causing Redraw .. MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3245 #endif
3246 MUI_Redraw(obj, MADF_DRAWOBJECT);
3247 goto draw_done;
3250 if (!(region = NewRegion()))
3252 #if defined(DEBUG_ILC_ICONRENDERING)
3253 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Couldnt Alloc Region -> Causing Redraw ...MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3254 #endif
3255 MUI_Redraw(obj, MADF_DRAWOBJECT);
3256 goto draw_done;
3259 if (data->update_scrolldx > 0)
3261 xrect.MinX = _mright(obj) - data->update_scrolldx;
3262 xrect.MinY = _mtop(obj);
3263 xrect.MaxX = _mright(obj);
3264 xrect.MaxY = _mbottom(obj);
3266 OrRectRegion(region, &xrect);
3268 data->update_rect1 = &xrect;
3270 else if (data->update_scrolldx < 0)
3272 xrect.MinX = _mleft(obj);
3273 xrect.MinY = _mtop(obj);
3274 xrect.MaxX = _mleft(obj) - data->update_scrolldx;
3275 xrect.MaxY = _mbottom(obj);
3277 OrRectRegion(region, &xrect);
3279 data->update_rect1 = &xrect;
3282 if (data->update_scrolldy > 0)
3284 yrect.MinX = _mleft(obj);
3285 yrect.MinY = _mbottom(obj) - data->update_scrolldy;
3286 if (((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3287 && (yrect.MinY < (_mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight)))
3289 xrect.MinY = data->icld_LVMAttribs->lmva_HeaderHeight;
3291 yrect.MaxX = _mright(obj);
3292 yrect.MaxY = _mbottom(obj);
3294 OrRectRegion(region, &yrect);
3296 data->update_rect2 = &yrect;
3298 else if (data->update_scrolldy < 0)
3300 yrect.MinX = _mleft(obj);
3301 yrect.MinY = _mtop(obj);
3302 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3304 xrect.MinY += data->icld_LVMAttribs->lmva_HeaderHeight;
3306 yrect.MaxX = _mright(obj);
3307 yrect.MaxY = _mtop(obj) - data->update_scrolldy;
3309 OrRectRegion(region, &yrect);
3311 data->update_rect2 = &yrect;
3314 #if defined(DEBUG_ILC_ICONRENDERING)
3315 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Scrolling Raster..\n", __PRETTY_FUNCTION__, draw_id));
3316 #endif
3317 if (data->icld_DisplayRastPort == data->icld_BufferRastPort)
3319 ScrollRasterBF(data->icld_BufferRastPort,
3320 data->update_scrolldx,
3321 data->update_scrolldy,
3322 _mleft(obj),
3323 _mtop(obj),
3324 _mright(obj),
3325 _mbottom(obj));
3327 else
3329 ScrollRasterBF(data->icld_BufferRastPort,
3330 data->update_scrolldx,
3331 data->update_scrolldy,
3334 _mwidth(obj) - 1,
3335 _mheight(obj) - 1);
3338 scroll_caused_damage = scroll_caused_damage && (_rp(obj)->Layer->Flags & LAYERREFRESH) ? TRUE : FALSE;
3340 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
3343 #if defined(DEBUG_ILC_ICONRENDERING)
3344 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3345 #endif
3346 MUI_Redraw(obj, MADF_DRAWOBJECT);
3348 data->update_rect1 = data->update_rect2 = NULL;
3350 if (!data->icld__Option_IconListFixedBackground)
3352 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
3354 if (scroll_caused_damage)
3356 if (MUI_BeginRefresh(muiRenderInfo(obj), 0))
3358 /* Theoretically it might happen that more damage is caused
3359 after ScrollRaster. By something else, like window movement
3360 in front of our window. Therefore refresh root object of
3361 window, not just this object */
3363 Object *o = NULL;
3365 GET(_win(obj),MUIA_Window_RootObject, &o);
3366 MUI_Redraw(o, MADF_DRAWOBJECT);
3367 #if defined(DEBUG_ILC_ICONRENDERING)
3368 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3369 #endif
3370 MUI_EndRefresh(muiRenderInfo(obj), 0);
3374 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3376 #if defined(DEBUG_ILC_ICONRENDERING)
3377 D(bug("[IconList] %s#%d: UPDATE_SCROLL: Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3378 #endif
3379 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3380 0, 0,
3381 data->icld_DisplayRastPort,
3382 _mleft(obj), _mtop(obj),
3383 _mwidth(obj), _mheight(obj),
3384 0xC0);
3386 goto draw_done;
3388 else if (data->icld_UpdateMode == UPDATE_RESIZE)
3390 struct Region *region = NULL;
3391 struct Rectangle wrect,
3392 hrect;
3393 ULONG diffw = 0,
3394 diffh = 0;
3396 #if defined(DEBUG_ILC_ICONRENDERING)
3397 D(bug("[IconList] %s#%d: UPDATE_RESIZE.\n", __PRETTY_FUNCTION__, draw_id));
3398 #endif
3400 if ((data->icld_BufferRastPort) && (data->icld_BufferRastPort != data->icld_DisplayRastPort))
3402 //Free up the buffers Layer, rastport and bitmap so we can replace them ..
3403 if ((GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_WIDTH) != data->icld_ViewWidth)
3404 || (GetBitMapAttr(data->icld_BufferRastPort->BitMap, BMA_HEIGHT) != data->icld_ViewHeight))
3406 struct Layer *oldLayer = data->icld_BufferRastPort->Layer;
3407 #if defined(DEBUG_ILC_ATTRIBS) && defined(DEBUG_ILC_ICONRENDERING)
3408 D(bug("[IconList] %s: Destroying old BackLayer\n", __PRETTY_FUNCTION__));
3409 #endif
3410 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3411 DeleteLayer(0, oldLayer);
3414 if (data->icld_BufferRastPort == data->icld_DisplayRastPort)
3416 struct Bitmap *bitmap_New;
3417 ULONG tmp_RastDepth;
3419 tmp_RastDepth = GetCyberMapAttr(data->icld_DisplayRastPort->BitMap, CYBRMATTR_DEPTH);
3420 if ((bitmap_New = (struct Bitmap *)AllocBitMap(data->icld_ViewWidth,
3421 data->icld_ViewHeight,
3422 tmp_RastDepth,
3423 BMF_CLEAR,
3424 data->icld_DisplayRastPort->BitMap))!=NULL)
3426 struct Layer * buffLayer = CreateLayerTagList(&_screen(obj)->LayerInfo,
3427 bitmap_New,
3430 data->icld_ViewWidth,
3431 data->icld_ViewHeight,
3432 LAYERSIMPLE,
3433 __iconList_BackBuffLayerTags);
3435 if (buffLayer != NULL)
3437 data->icld_BufferRastPort = buffLayer->rp;
3438 #if defined(DEBUG_ILC_ATTRIBS) && defined(DEBUG_ILC_ICONRENDERING)
3439 D(bug("[IconList] %s: FrontRastPort @ %p, New BackLayer @ %p, BackRastport @ %p\n", __PRETTY_FUNCTION__, data->icld_DisplayRastPort, data->icld_BufferRastPort->Layer, data->icld_BufferRastPort));
3440 #endif
3441 SET(obj, MUIA_IconList_BufferRastport, data->icld_BufferRastPort);
3442 data->icld_DrawOffsetX = 0;
3443 data->icld_DrawOffsetY = 0;
3445 else
3447 FreeBitMap(bitmap_New);
3448 data->icld_BufferRastPort = data->icld_DisplayRastPort;
3449 data->icld_DrawOffsetX = _mleft(obj);
3450 data->icld_DrawOffsetY = _mtop(obj);
3456 data->icld_UpdateMode = 0;
3458 if (!data->icld__Option_IconListScaledBackground)
3460 if (!(region = NewRegion()))
3462 #if defined(DEBUG_ILC_ICONRENDERING)
3463 D(bug("[IconList] %s#%d: UPDATE_RESIZE: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3464 #endif
3465 MUI_Redraw(obj, MADF_DRAWOBJECT);
3466 goto draw_done;
3469 if ( data->icld_ViewWidth > update_oldwidth )
3470 diffw = data->icld_ViewWidth - update_oldwidth;
3471 if ( data->icld_ViewHeight > update_oldheight )
3472 diffh = data->icld_ViewHeight - update_oldheight;
3474 if (diffw)
3476 wrect.MinX = _mright(obj) - diffw;
3477 wrect.MinY = _mtop(obj);
3478 wrect.MaxX = _mright(obj);
3479 wrect.MaxY = _mbottom(obj);
3480 OrRectRegion(region, &wrect);
3481 data->update_rect1 = &wrect;
3484 if (diffh)
3486 hrect.MinX = _mleft(obj);
3487 hrect.MinY = _mbottom(obj) - diffh;
3488 hrect.MaxX = _mright(obj);
3489 hrect.MaxX = _mright(obj);
3490 hrect.MaxY = _mbottom(obj);
3491 OrRectRegion(region, &hrect);
3492 data->update_rect2 = &hrect;
3494 if (diffh||diffw)
3496 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
3498 else
3500 /* View became smaller both in horizontal and vertical direction.
3501 Nothing to do */
3503 DisposeRegion(region);
3504 goto draw_done;
3508 #if defined(DEBUG_ILC_ICONRENDERING)
3509 D(bug("[IconList] %s#%d: UPDATE_RESIZE: Causing Redraw -> MADF_DRAWOBJECT..\n", __PRETTY_FUNCTION__, draw_id));
3510 #endif
3511 MUI_Redraw(obj, MADF_DRAWOBJECT);
3513 if (!data->icld__Option_IconListScaledBackground)
3515 if (diffh||diffw)
3517 data->update_rect1 = data->update_rect2 = NULL;
3518 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
3519 } else DisposeRegion(region);
3522 goto draw_done;
3526 if (message->flags & MADF_DRAWOBJECT)
3528 struct Rectangle viewrect;
3529 int current = 0, first = 0, visible = 0;
3531 #if defined(DEBUG_ILC_ICONRENDERING)
3532 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT\n", __PRETTY_FUNCTION__, draw_id));
3533 #endif
3535 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3537 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), data->icld_LVMAttribs->lmva_HeaderHeight);
3538 RenderListViewModeHeader(obj, data);
3539 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3541 viewrect.MinY = _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight;
3543 first = FirstVisibleLine(data);
3544 visible = NumVisibleLines(data);
3546 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj) + data->icld_LVMAttribs->lmva_HeaderHeight, _mwidth(obj), _mheight(obj) - data->icld_LVMAttribs->lmva_HeaderHeight);
3548 else
3550 viewrect.MinY = _mtop(obj);
3551 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj));
3554 viewrect.MaxY = _mtop(obj) + _mheight(obj) - 1;
3555 viewrect.MinX = _mleft(obj);
3556 viewrect.MaxX = _mleft(obj) + _mwidth(obj) - 1;
3558 #if defined(DEBUG_ILC_ICONRENDERING)
3559 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT: Calling MUIM_DrawBackground (B)\n", __PRETTY_FUNCTION__, draw_id));
3560 #endif
3561 DoMethod(
3562 obj, MUIM_DrawBackground, viewrect.MinX, viewrect.MinY, (viewrect.MaxX - viewrect.MinX) + 1, (viewrect.MaxY - viewrect.MinY) + 1,
3563 clear_xoffset, clear_yoffset, 0
3565 #if defined(__AROS__)
3566 ForeachNode(&data->icld_IconList, entry)
3567 #else
3568 Foreach_Node(&data->icld_IconList, entry);
3569 #endif
3571 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
3573 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
3575 if ((current >= first) && (current <= (first + visible)))
3577 DoMethod(obj, MUIM_IconList_DrawEntry, entry, current);
3579 current++;
3582 else
3584 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
3585 (entry->ie_DiskObj) &&
3586 (entry->ie_IconX != NO_ICON_POSITION) &&
3587 (entry->ie_IconY != NO_ICON_POSITION))
3589 struct Rectangle iconrect;
3590 IconList_GetIconAreaRectangle(obj, data, entry, &iconrect);
3592 iconrect.MinX += viewrect.MinX - data->icld_ViewX + entry->ie_IconX;
3593 iconrect.MaxX += viewrect.MinX - data->icld_ViewX + entry->ie_IconX;
3594 iconrect.MinY += viewrect.MinY - data->icld_ViewY + entry->ie_IconY;
3595 iconrect.MaxY += viewrect.MinY - data->icld_ViewY + entry->ie_IconY;
3597 if (RectAndRect(&viewrect, &iconrect))
3599 DoMethod(obj, MUIM_IconList_DrawEntry, entry, ICONENTRY_DRAWMODE_PLAIN);
3600 DoMethod(obj, MUIM_IconList_DrawEntryLabel, entry, ICONENTRY_DRAWMODE_PLAIN);
3606 if (data->icld_DisplayRastPort != data->icld_BufferRastPort)
3608 #if defined(DEBUG_ILC_ICONRENDERING)
3609 D(bug("[IconList] %s#%d: MADF_DRAWOBJECT: Blitting to front rastport..\n", __PRETTY_FUNCTION__, draw_id));
3610 #endif
3611 BltBitMapRastPort(data->icld_BufferRastPort->BitMap,
3612 0, 0,
3613 data->icld_DisplayRastPort,
3614 _mleft(obj), _mtop(obj),
3615 _mwidth(obj), _mheight(obj),
3616 0xC0);
3619 MUI_RemoveClipping(muiRenderInfo(obj), clip);
3621 data->icld_UpdateMode = 0;
3623 draw_done:;
3625 #if defined(DEBUG_ILC_ICONRENDERING)
3626 D(bug("[IconList] %s: Draw finished for id %d\n", __PRETTY_FUNCTION__, draw_id));
3627 #endif
3628 return 0;
3632 ///IconList__MUIM_IconList_Update()
3633 /**************************************************************************
3634 MUIM_IconList_Refresh
3635 Implemented by subclasses
3636 **************************************************************************/
3637 IPTR IconList__MUIM_IconList_Update(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Update *message)
3639 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3641 #if defined(DEBUG_ILC_FUNCS)
3642 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3643 #endif
3645 data->icld_FocusIcon = NULL;
3646 SET(obj, MUIA_IconList_Changed, TRUE);
3648 return 1;
3652 ///MUIM_IconList_Clear()
3653 /**************************************************************************
3654 MUIM_IconList_Clear
3655 **************************************************************************/
3656 IPTR IconList__MUIM_IconList_Clear(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Clear *message)
3658 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3659 struct IconEntry *node = NULL;
3661 #if defined(DEBUG_ILC_FUNCS)
3662 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3663 #endif
3665 while ((node = (struct IconEntry*)RemTail((struct List*)&data->icld_IconList)))
3667 DoMethod(obj, MUIM_IconList_DestroyEntry, node);
3670 data->icld_SelectionLastClicked = NULL;
3671 data->icld_FocusIcon = NULL;
3673 data->icld_ViewX = data->icld_ViewY = data->icld_AreaWidth = data->icld_AreaHeight = 0;
3675 D(bug("[IconList]: %s: call SetSuperAttrs()\n", __PRETTY_FUNCTION__));
3676 SetSuperAttrs(CLASS, obj, MUIA_Virtgroup_Left, data->icld_ViewX,
3677 MUIA_Virtgroup_Top, data->icld_ViewY,
3678 TAG_DONE);
3680 D(bug("[IconList]: %s: call SetAttrs()\n", __PRETTY_FUNCTION__));
3681 SetAttrs(obj, MUIA_Virtgroup_Left, data->icld_ViewX,
3682 MUIA_Virtgroup_Top, data->icld_ViewY,
3683 TAG_DONE);
3685 D(bug("[IconList]: %s: Set MUIA_IconList_Width and MUIA_IconList_Height\n", __PRETTY_FUNCTION__));
3686 SetAttrs(obj, MUIA_IconList_Width, data->icld_AreaWidth,
3687 MUIA_IconList_Height, data->icld_AreaHeight,
3688 TAG_DONE);
3690 D(bug("[IconList]: %s: call MUI_Redraw()\n", __PRETTY_FUNCTION__));
3691 MUI_Redraw(obj,MADF_DRAWOBJECT);
3692 return 1;
3696 ///IconList__MUIM_IconList_DestroyEntry()
3697 IPTR IconList__MUIM_IconList_DestroyEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DestroyEntry *message)
3699 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3701 #if defined(DEBUG_ILC_FUNCS)
3702 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3703 #endif
3705 if (message->entry)
3707 if (message->entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
3709 if (data->icld_SelectionLastClicked == message->entry)
3711 struct IconList_Entry *nextentry = &message->entry->ie_IconListEntry;
3713 /* get selected entries from SOURCE iconlist */
3714 DoMethod(obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&nextentry);
3715 if ((nextentry) && (nextentry != (IPTR)MUIV_IconList_NextIcon_End))
3716 data->icld_SelectionLastClicked = (struct IconEntry *)((IPTR)nextentry - ((IPTR)&message->entry->ie_IconListEntry - (IPTR)message->entry));
3717 else
3718 data->icld_SelectionLastClicked = NULL;
3720 if (data->icld_FocusIcon == message->entry)
3721 data->icld_FocusIcon = data->icld_SelectionLastClicked;
3723 Remove(&message->entry->ie_SelectionNode);
3726 if (message->entry->ie_TxtBuf_DisplayedLabel)
3727 FreeVecPooled(data->icld_Pool, message->entry->ie_TxtBuf_DisplayedLabel);
3729 if (message->entry->ie_TxtBuf_PROT)
3730 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_PROT, 8);
3732 if (message->entry->ie_TxtBuf_SIZE)
3733 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_SIZE, 30);
3735 if (message->entry->ie_TxtBuf_TIME)
3736 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_TIME, LEN_DATSTRING);
3738 if (message->entry->ie_TxtBuf_DATE)
3739 FreePooled(data->icld_Pool, message->entry->ie_TxtBuf_DATE, LEN_DATSTRING);
3741 if (message->entry->ie_DiskObj)
3742 FreeDiskObject(message->entry->ie_DiskObj);
3744 if (message->entry->ie_FileInfoBlock)
3745 FreeMem(message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
3747 if (message->entry->ie_IconListEntry.label)
3748 FreePooled(data->icld_Pool, message->entry->ie_IconListEntry.label, strlen(message->entry->ie_IconListEntry.label)+1);
3750 if (message->entry->ie_IconNode.ln_Name)
3751 FreePooled(data->icld_Pool, message->entry->ie_IconNode.ln_Name, strlen(message->entry->ie_IconNode.ln_Name)+1);
3753 FreePooled(data->icld_Pool, message->entry, sizeof(struct IconEntry));
3755 return (IPTR)TRUE;
3759 ///IconList__MUIM_IconList_CreateEntry()
3760 /**************************************************************************
3761 MUIM_IconList_CreateEntry.
3762 Returns 0 on failure otherwise it returns the icons entry ..
3763 **************************************************************************/
3764 IPTR IconList__MUIM_IconList_CreateEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_CreateEntry *message)
3766 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3767 struct IconEntry *entry = NULL;
3768 struct DateTime dt;
3769 struct DateStamp now;
3770 UBYTE *sp = NULL;
3772 struct DiskObject *dob = NULL;
3773 struct Rectangle rect;
3775 IPTR geticon_error = 0;
3777 #if defined(DEBUG_ILC_FUNCS)
3778 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3779 #endif
3781 /*disk object (icon)*/
3782 if (message->entry_dob == NULL)
3784 IPTR iconlistScreen = _screen(obj);
3785 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
3787 dob = GetIconTags
3789 message->filename,
3790 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
3791 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
3792 ICONGETA_FailIfUnavailable, FALSE,
3793 ICONGETA_GenerateImageMasks, TRUE,
3794 ICONA_ErrorCode, &geticon_error,
3795 TAG_DONE
3798 if (dob == NULL)
3800 D(bug("[IconList] %s: Fatal: Couldnt get DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
3802 return (IPTR)NULL;
3805 else
3807 dob = message->entry_dob;
3810 D(bug("[IconList] %s: DiskObject @ 0x%p\n", __PRETTY_FUNCTION__, dob));
3812 if ((entry = AllocPooled(data->icld_Pool, sizeof(struct IconEntry))) == NULL)
3814 D(bug("[IconList] %s: Failed to Allocate Entry Storage!\n", __PRETTY_FUNCTION__));
3815 FreeDiskObject(dob);
3816 return (IPTR)NULL;
3818 memset(entry, 0, sizeof(struct IconEntry));
3819 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
3820 entry->ie_IconListEntry.ile_IconEntry = entry;
3822 /* Allocate Text Buffers */
3824 if ((entry->ie_TxtBuf_DATE = AllocPooled(data->icld_Pool, LEN_DATSTRING)) == NULL)
3826 D(bug("[IconList] %s: Failed to Allocate Entry DATE Storage!\n", __PRETTY_FUNCTION__));
3827 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
3828 return (IPTR)NULL;
3830 memset(entry->ie_TxtBuf_DATE, 0, LEN_DATSTRING);
3832 if ((entry->ie_TxtBuf_TIME = AllocPooled(data->icld_Pool, LEN_DATSTRING)) == NULL)
3834 D(bug("[IconList] %s: Failed to Allocate Entry TIME string Storage!\n", __PRETTY_FUNCTION__));
3835 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
3836 return (IPTR)NULL;
3838 memset(entry->ie_TxtBuf_TIME, 0, LEN_DATSTRING);
3840 if ((entry->ie_TxtBuf_SIZE = AllocPooled(data->icld_Pool, 30)) == NULL)
3842 D(bug("[IconList] %s: Failed to Allocate Entry SIZE string Storage!\n", __PRETTY_FUNCTION__));
3843 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
3844 return (IPTR)NULL;
3846 memset(entry->ie_TxtBuf_SIZE, 0, 30);
3848 if ((entry->ie_TxtBuf_PROT = AllocPooled(data->icld_Pool, 8)) == NULL)
3850 D(bug("[IconList] %s: Failed to Allocate Entry PROT Flag string Storage!\n", __PRETTY_FUNCTION__));
3851 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
3852 return (IPTR)NULL;
3854 memset(entry->ie_TxtBuf_PROT, 0, 8);
3856 /*alloc filename*/
3857 if ((entry->ie_IconNode.ln_Name = AllocPooled(data->icld_Pool, strlen(message->filename) + 1)) == NULL)
3859 D(bug("[IconList] %s: Failed to Allocate Entry filename string Storage!\n", __PRETTY_FUNCTION__));
3860 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
3861 return (IPTR)NULL;
3864 /*alloc entry label*/
3865 if ((entry->ie_IconListEntry.label = AllocPooled(data->icld_Pool, strlen(message->label) + 1)) == NULL)
3867 D(bug("[IconList] %s: Failed to Allocate Entry label string Storage!\n", __PRETTY_FUNCTION__));
3868 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
3869 return (IPTR)NULL;
3872 /*file info block*/
3873 if(message->fib != NULL)
3875 if ((entry->ie_FileInfoBlock = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)) != NULL)
3877 CopyMem(message->fib, entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
3879 if (entry->ie_FileInfoBlock->fib_DirEntryType > 0)
3881 strcpy(entry->ie_TxtBuf_SIZE, "Drawer");
3883 else
3885 FmtSizeToString(entry->ie_TxtBuf_SIZE, entry->ie_FileInfoBlock->fib_Size);
3888 dt.dat_Stamp = entry->ie_FileInfoBlock->fib_Date;
3889 dt.dat_Format = FORMAT_DEF;
3890 dt.dat_Flags = 0;
3891 dt.dat_StrDay = NULL;
3892 dt.dat_StrDate = entry->ie_TxtBuf_DATE;
3893 dt.dat_StrTime = entry->ie_TxtBuf_TIME;
3895 DateToStr(&dt);
3896 DateStamp(&now);
3898 /*if modified today show time, otherwise just show date*/
3899 if (now.ds_Days == entry->ie_FileInfoBlock->fib_Date.ds_Days)
3900 entry->ie_Flags |= ICONENTRY_FLAG_TODAY;
3901 else
3902 entry->ie_Flags &= ~ICONENTRY_FLAG_TODAY;
3904 sp = entry->ie_TxtBuf_PROT;
3905 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_SCRIPT) ? 's' : '-';
3906 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_PURE) ? 'p' : '-';
3907 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
3908 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_READ) ? '-' : 'r';
3909 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_WRITE) ? '-' : 'w';
3910 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
3911 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_DELETE) ? '-' : 'd';
3912 *sp++ = '\0';
3914 entry->ie_IconListEntry.type = entry->ie_FileInfoBlock->fib_DirEntryType;
3917 else
3919 entry->ie_IconListEntry.type = ST_USERDIR;
3922 /* Override type if specified during createntry */
3923 if (message->type != 0)
3925 entry->ie_IconListEntry.type = message->type;
3926 D(bug("[IconList] %s: Overide Entry Type. New Type = %x\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.type));
3928 else
3930 D(bug("[IconList] %s: Entry Type = %x\n", __PRETTY_FUNCTION__, entry->ie_IconListEntry.type));
3933 strcpy(entry->ie_IconNode.ln_Name, message->filename);
3934 strcpy(entry->ie_IconListEntry.label, message->label);
3936 entry->ie_IconListEntry.udata = NULL;
3938 if (IconList__LabelFunc_CreateLabel(obj, data, entry) != (IPTR)NULL)
3940 entry->ie_DiskObj = dob;
3942 /* Use a geticonrectangle routine that gets textwidth! */
3943 IconList_GetIconAreaRectangle(obj, data, entry, &rect);
3945 return (IPTR)entry;
3948 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
3949 return (IPTR)NULL;
3953 ///IconList__MUIM_IconList_UpdateEntry()
3954 /**************************************************************************
3955 MUIM_IconList_UpdateEntry.
3956 Returns 0 on failure otherwise it returns the icons entry ..
3957 **************************************************************************/
3958 IPTR IconList__MUIM_IconList_UpdateEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_UpdateEntry *message)
3960 struct IconList_DATA *data = INST_DATA(CLASS, obj);
3961 struct DateTime dt;
3962 struct DateStamp now;
3963 UBYTE *sp = NULL;
3965 struct DiskObject *dob = NULL;
3966 struct Rectangle rect;
3968 IPTR geticon_error = 0;
3970 #if defined(DEBUG_ILC_FUNCS)
3971 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
3972 #endif
3974 /* Update disk object (icon)*/
3975 /* if (message->entry_dob == NULL)
3977 IPTR iconlistScreen = _screen(obj);
3978 D(bug("[IconList] %s: IconList Screen @ 0x%p)\n", __PRETTY_FUNCTION__, iconlistScreen));
3980 dob = GetIconTags
3982 message->filename,
3983 (iconlistScreen) ? ICONGETA_Screen : TAG_IGNORE, iconlistScreen,
3984 (iconlistScreen) ? ICONGETA_RemapIcon : TAG_IGNORE, TRUE,
3985 ICONGETA_FailIfUnavailable, FALSE,
3986 ICONGETA_GenerateImageMasks, TRUE,
3987 ICONA_ErrorCode, &geticon_error,
3988 TAG_DONE
3991 if (dob == NULL)
3993 D(bug("[IconList] %s: Fatal: Couldnt get DiskObject! (error code = 0x%p)\n", __PRETTY_FUNCTION__, geticon_error));
3995 return (IPTR)NULL;
3998 else
4000 dob = message->entry_dob;
4003 D(bug("[IconList] %s: DiskObject @ 0x%p\n", __PRETTY_FUNCTION__, dob));
4006 /* Update filename */
4007 if (strcmp(message->entry->ie_IconNode.ln_Name, message->filename) != 0)
4009 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4010 FreePooled(data->icld_Pool, message->entry->ie_IconNode.ln_Name, strlen(message->entry->ie_IconNode.ln_Name) + 1);
4011 if ((message->entry->ie_IconNode.ln_Name = AllocPooled(data->icld_Pool, strlen(message->filename) + 1)) == NULL)
4013 D(bug("[IconList] %s: Failed to Allocate Entry filename string Storage!\n", __PRETTY_FUNCTION__));
4014 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4015 return (IPTR)NULL;
4017 strcpy(message->entry->ie_IconNode.ln_Name, message->filename);
4020 /* Update entry label */
4021 if (strcmp(message->entry->ie_IconListEntry.label, message->label) != 0)
4023 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4024 FreePooled(data->icld_Pool, message->entry->ie_IconListEntry.label, strlen(message->entry->ie_IconListEntry.label) + 1);
4025 if ((message->entry->ie_IconListEntry.label = AllocPooled(data->icld_Pool, strlen(message->label) + 1)) == NULL)
4027 D(bug("[IconList] %s: Failed to Allocate Entry label string Storage!\n", __PRETTY_FUNCTION__));
4028 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4029 return (IPTR)NULL;
4031 strcpy(message->entry->ie_IconListEntry.label, message->label);
4032 if (IconList__LabelFunc_CreateLabel(obj, data, message->entry) == (IPTR)NULL)
4034 D(bug("[IconList] %s: Failed to create label\n", __PRETTY_FUNCTION__));
4035 DoMethod(obj, MUIM_IconList_DestroyEntry, message->entry);
4036 return (IPTR)NULL;
4040 /* Update file info block */
4041 if(message->fib != NULL)
4043 if (!(message->entry->ie_FileInfoBlock))
4045 if ((message->entry->ie_FileInfoBlock = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)) != NULL)
4047 CopyMem(message->fib, message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4051 /* if (entry->ie_FileInfoBlock->fib_DirEntryType > 0)
4053 strcpy(entry->ie_TxtBuf_SIZE, "Drawer");
4055 else
4057 FmtSizeToString(entry->ie_TxtBuf_SIZE, entry->ie_FileInfoBlock->fib_Size);
4060 dt.dat_Stamp = entry->ie_FileInfoBlock->fib_Date;
4061 dt.dat_Format = FORMAT_DEF;
4062 dt.dat_Flags = 0;
4063 dt.dat_StrDay = NULL;
4064 dt.dat_StrDate = entry->ie_TxtBuf_DATE;
4065 dt.dat_StrTime = entry->ie_TxtBuf_TIME;
4067 DateToStr(&dt);
4068 DateStamp(&now);
4070 //if modified today show time, otherwise just show date
4071 if (now.ds_Days == entry->ie_FileInfoBlock->fib_Date.ds_Days)
4072 entry->ie_Flags |= ICONENTRY_FLAG_TODAY;
4073 else
4074 entry->ie_Flags &= ~ICONENTRY_FLAG_TODAY;
4076 sp = entry->ie_TxtBuf_PROT;
4077 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_SCRIPT) ? 's' : '-';
4078 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_PURE) ? 'p' : '-';
4079 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
4080 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_READ) ? '-' : 'r';
4081 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_WRITE) ? '-' : 'w';
4082 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
4083 *sp++ = (entry->ie_FileInfoBlock->fib_Protection & FIBF_DELETE) ? '-' : 'd';
4084 *sp++ = '\0';
4086 entry->ie_IconListEntry.type = entry->ie_FileInfoBlock->fib_DirEntryType;
4089 else
4091 if (message->entry->ie_FileInfoBlock)
4092 FreeMem(message->entry->ie_FileInfoBlock, sizeof(struct FileInfoBlock));
4094 if (message->entry->ie_IconListEntry.type != ST_USERDIR)
4096 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4097 message->entry->ie_IconListEntry.type = ST_USERDIR;
4101 /* Override type if specified */
4102 if ((message->type != 0) && (message->entry->ie_IconListEntry.type != message->type))
4104 message->entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
4105 message->entry->ie_IconListEntry.type = message->type;
4106 D(bug("[IconList] %s: Overide Entry Type. New Type = %x\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.type));
4108 else
4110 D(bug("[IconList] %s: Entry Type = %x\n", __PRETTY_FUNCTION__, message->entry->ie_IconListEntry.type));
4113 IconList_GetIconAreaRectangle(obj, data, message->entry, &rect);
4115 return (IPTR)message->entry;
4119 ///DoWheelMove()
4120 static void DoWheelMove(struct IClass *CLASS, Object *obj, LONG wheelx, LONG wheely, UWORD qual)
4122 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4124 LONG newleft = data->icld_ViewX,
4125 newtop = data->icld_ViewY;
4127 /* Use horizontal scrolling if any of the following cases are true ...
4129 # vertical wheel is used but there's nothing to scroll
4130 (everything is visible already) ..
4132 # vertical wheel is used and one of the ALT keys is down. */
4134 if ((wheely && !wheelx) &&
4135 ((data->icld_AreaHeight <= _mheight(obj)) || (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))))
4137 wheelx = wheely; wheely = 0;
4140 if (qual & (IEQUALIFIER_CONTROL))
4142 if (wheelx < 0) newleft = 0;
4143 if (wheelx > 0) newleft = data->icld_AreaWidth;
4144 if (wheely < 0) newtop = 0;
4145 if (wheely > 0) newtop = data->icld_AreaHeight;
4147 else if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
4149 newleft += (wheelx * _mwidth(obj));
4150 newtop += (wheely * _mheight(obj));
4152 else
4154 newleft += wheelx * 30;
4155 newtop += wheely * 30;
4158 if (newleft + _mwidth(obj) > data->icld_AreaWidth)
4159 newleft = data->icld_AreaWidth - _mwidth(obj);
4160 if (newleft < 0)
4161 newleft = 0;
4163 if (newtop + _mheight(obj) > data->icld_AreaHeight)
4164 newtop = data->icld_AreaHeight - _mheight(obj);
4165 if (newtop < 0)
4166 newtop = 0;
4168 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
4170 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
4171 MUIA_Virtgroup_Top, newtop,
4172 TAG_DONE);
4177 ///MUIM_HandleEvent()
4178 /**************************************************************************
4179 MUIM_HandleEvent
4180 **************************************************************************/
4181 IPTR IconList__MUIM_HandleEvent(struct IClass *CLASS, Object *obj, struct MUIP_HandleEvent *message)
4183 struct IconList_DATA *data = INST_DATA(CLASS, obj);
4185 #if defined(DEBUG_ILC_FUNCS)
4186 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
4187 #endif
4189 if (message->imsg)
4191 LONG mx = message->imsg->MouseX - _mleft(obj);
4192 LONG my = message->imsg->MouseY - _mtop(obj);
4194 LONG wheelx = 0;
4195 LONG wheely = 0;
4197 switch (message->imsg->Class)
4199 case IDCMP_NEWSIZE:
4200 bug("[IconList] %s: IDCMP_NEWSIZE\n", __PRETTY_FUNCTION__);
4201 break;
4203 case IDCMP_RAWKEY:
4205 #if defined(DEBUG_ILC_EVENTS)
4206 D(bug("[IconList] %s: IDCMP_RAWKEY\n", __PRETTY_FUNCTION__));
4207 #endif
4208 BOOL rawkey_handled = FALSE;
4210 switch(message->imsg->Code)
4212 case RAWKEY_NM_WHEEL_UP:
4213 wheely = -1;
4214 rawkey_handled = TRUE;
4215 break;
4217 case RAWKEY_NM_WHEEL_DOWN:
4218 wheely = 1;
4219 rawkey_handled = TRUE;
4220 break;
4222 case RAWKEY_NM_WHEEL_LEFT:
4223 wheelx = -1;
4224 rawkey_handled = TRUE;
4225 break;
4227 case RAWKEY_NM_WHEEL_RIGHT:
4228 wheelx = 1;
4229 rawkey_handled = TRUE;
4230 break;
4233 if (rawkey_handled)
4235 #if defined(DEBUG_ILC_KEYEVENTS)
4236 D(bug("[IconList] %s: Processing mouse wheel event\n", __PRETTY_FUNCTION__));
4237 #endif
4238 if (_isinobject(message->imsg->MouseX, message->imsg->MouseY) &&
4239 (wheelx || wheely))
4241 DoWheelMove(CLASS, obj, wheelx, wheely, message->imsg->Qualifier);
4244 else if (!(message->imsg->Code & IECODE_UP_PREFIX))
4246 LONG new_ViewY = data->icld_ViewY;
4247 struct IconEntry *start_entry = NULL, *active_entry = NULL, *entry_next = NULL;
4248 IPTR start_X = 0, start_Y = 0, active_X = 0, active_Y = 0, next_X = 0, next_Y = 0;
4249 IPTR x_diff = 0;
4251 #if defined(DEBUG_ILC_KEYEVENTS)
4252 D(bug("[IconList] %s: Processing key up event\n", __PRETTY_FUNCTION__));
4253 #endif
4255 switch(message->imsg->Code)
4257 case RAWKEY_RETURN:
4258 rawkey_handled = TRUE;
4260 #if defined(DEBUG_ILC_KEYEVENTS)
4261 D(bug("[IconList] %s: RAWKEY_RETURN\n", __PRETTY_FUNCTION__));
4262 #endif
4264 if (data->icld_FocusIcon) active_entry = data->icld_FocusIcon;
4265 else if (data->icld_SelectionLastClicked) active_entry = data->icld_SelectionLastClicked;
4267 if (active_entry)
4269 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
4271 active_entry->ie_Flags |= ICONENTRY_FLAG_SELECTED;
4272 AddTail(&data->icld_SelectionList, &active_entry->ie_SelectionNode);
4273 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4274 data->update_entry = active_entry;
4275 MUI_Redraw(obj, MADF_DRAWUPDATE);
4277 data->icld_SelectionLastClicked = active_entry;
4278 data->icld_FocusIcon = active_entry;
4280 SET(obj, MUIA_IconList_DoubleClick, TRUE);
4282 break;
4284 case RAWKEY_SPACE:
4285 rawkey_handled = TRUE;
4287 #if defined(DEBUG_ILC_KEYEVENTS)
4288 D(bug("[IconList] %s: RAWKEY_SPACE\n", __PRETTY_FUNCTION__));
4289 #endif
4291 if (data->icld_FocusIcon) active_entry = data->icld_FocusIcon;
4292 else if (data->icld_SelectionLastClicked) active_entry = data->icld_SelectionLastClicked;
4294 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)||(data->icld_SelectionLastClicked != active_entry)))
4296 #if defined(DEBUG_ILC_KEYEVENTS)
4297 D(bug("[IconList] %s: SPACE: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
4298 #endif
4299 DoMethod(obj, MUIM_IconList_UnselectAll);
4302 if (active_entry)
4304 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
4306 AddTail(&data->icld_SelectionList, &active_entry->ie_SelectionNode);
4307 active_entry->ie_Flags |= ICONENTRY_FLAG_SELECTED;
4308 data->icld_SelectionLastClicked = active_entry;
4310 else
4312 Remove(&active_entry->ie_SelectionNode);
4313 active_entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
4316 data->icld_FocusIcon = active_entry;
4318 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4319 data->update_entry = active_entry;
4320 MUI_Redraw(obj, MADF_DRAWUPDATE);
4322 break;
4324 case RAWKEY_PAGEUP:
4325 rawkey_handled = TRUE;
4327 #if defined(DEBUG_ILC_KEYEVENTS)
4328 D(bug("[IconList] %s: RAWKEY_PAGEUP\n", __PRETTY_FUNCTION__));
4329 #endif
4331 if (data->icld_AreaHeight > data->icld_ViewHeight)
4333 new_ViewY -= data->icld_ViewHeight;
4334 if (new_ViewY< 0)
4335 new_ViewY = 0;
4338 if (new_ViewY != data->icld_ViewY)
4340 SET(obj, MUIA_Virtgroup_Top, new_ViewY);
4342 break;
4344 case RAWKEY_PAGEDOWN:
4345 rawkey_handled = TRUE;
4347 #if defined(DEBUG_ILC_KEYEVENTS)
4348 D(bug("[IconList] %s: RAWKEY_PAGEDOWN\n", __PRETTY_FUNCTION__));
4349 #endif
4351 if (data->icld_AreaHeight > data->icld_ViewHeight)
4353 new_ViewY += data->icld_ViewHeight;
4354 if (new_ViewY > (data->icld_AreaHeight - data->icld_ViewHeight))
4355 new_ViewY = data->icld_AreaHeight - data->icld_ViewHeight;
4358 if (new_ViewY != data->icld_ViewY)
4360 SET(obj, MUIA_Virtgroup_Top, new_ViewY);
4362 break;
4364 case RAWKEY_UP:
4365 rawkey_handled = TRUE;
4367 #if defined(DEBUG_ILC_KEYEVENTS)
4368 D(bug("[IconList] %s: RAWKEY_UP\n", __PRETTY_FUNCTION__));
4369 #endif
4371 if (data->icld_FocusIcon)
4373 start_entry = data->icld_FocusIcon;
4374 #if defined(DEBUG_ILC_KEYEVENTS)
4375 D(bug("[IconList] %s: UP: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
4376 #endif
4378 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
4379 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4380 data->update_entry = start_entry;
4381 MUI_Redraw(obj, MADF_DRAWUPDATE);
4383 start_X = start_entry->ie_IconX;
4384 start_Y = start_entry->ie_IconY;
4385 #if defined(DEBUG_ILC_KEYEVENTS)
4386 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));
4387 #endif
4388 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4390 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4392 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
4393 #if defined(DEBUG_ILC_KEYEVENTS)
4394 D(bug("[IconList] %s: UP: adjusted start_X for grid = %d\n", __PRETTY_FUNCTION__, start_X));
4395 #endif
4399 if ((active_entry = Node_PreviousVisible(start_entry)) && !(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
4401 //Check if we are at the edge of the entry area ..
4402 #if defined(DEBUG_ILC_KEYEVENTS)
4403 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));
4404 #endif
4405 active_Y = active_entry->ie_IconY;
4407 if (active_Y == start_Y)
4410 #if defined(DEBUG_ILC_KEYEVENTS)
4411 D(bug("[IconList] %s: UP: active_entry is on our row (not at the edge)\n", __PRETTY_FUNCTION__));
4412 #endif
4413 entry_next = active_entry;
4414 next_X = entry_next->ie_IconX;
4415 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4417 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4418 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
4422 #if defined(DEBUG_ILC_KEYEVENTS)
4423 D(bug("[IconList] %s: UP: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
4424 #endif
4427 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
4429 #if defined(DEBUG_ILC_KEYEVENTS)
4430 D(bug("[IconList] %s: UP: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
4431 #endif
4432 DoMethod(obj, MUIM_IconList_UnselectAll);
4435 #if defined(DEBUG_ILC_KEYEVENTS)
4436 D(bug("[IconList] %s: UP: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
4437 #endif
4438 if (!(active_entry))
4440 // If nothing is selected we will use the last visible entry ..
4441 active_entry = Node_LastVisible(&data->icld_IconList);
4442 start_X = active_entry->ie_IconX;
4443 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4445 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4446 start_X = start_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
4448 start_Y = active_entry->ie_IconY;
4451 while (active_entry != NULL)
4453 #if defined(DEBUG_ILC_KEYEVENTS)
4454 D(bug("[IconList] %s: UP: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
4455 #endif
4456 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
4458 // Return the first visible since the list flow direction matches
4459 // our cursor direction
4460 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4461 break;
4463 else
4465 active_X = active_entry->ie_IconX;
4467 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4469 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4470 x_diff = ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
4472 active_Y = active_entry->ie_IconY;
4474 if (start_entry)
4476 if (entry_next)
4478 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
4479 (active_Y < start_Y) &&
4480 (((active_X - x_diff) >= start_X ) &&
4481 ((active_X - x_diff) <= (start_X + start_entry->ie_AreaWidth + (x_diff*2)))))
4483 #if defined(DEBUG_ILC_KEYEVENTS)
4484 D(bug("[IconList] %s: UP: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
4485 #endif
4486 break;
4488 else if (active_entry == (struct IconEntry *)GetHead(&data->icld_IconList))
4490 #if defined(DEBUG_ILC_KEYEVENTS)
4491 D(bug("[IconList] %s: UP: (A) reached list start .. restarting from the end ..\n", __PRETTY_FUNCTION__));
4492 #endif
4493 start_X = next_X;
4495 if ((entry_next = Node_PreviousVisible(entry_next)))
4497 if (entry_next->ie_IconX > start_X)
4498 entry_next = NULL;
4499 else
4501 next_X = entry_next->ie_IconX;
4502 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4504 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4505 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
4509 start_Y = 0;
4510 #if defined(DEBUG_ILC_KEYEVENTS)
4511 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));
4512 #endif
4513 active_entry = Node_LastVisible(&data->icld_IconList);
4516 else
4518 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
4519 (active_Y < start_Y) &&
4520 ((active_X + x_diff) < (start_X + start_entry->ie_AreaWidth + x_diff)))
4522 #if defined(DEBUG_ILC_KEYEVENTS)
4523 D(bug("[IconList] %s: UP: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
4524 #endif
4525 break;
4529 else
4531 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4533 #if defined(DEBUG_ILC_KEYEVENTS)
4534 D(bug("[IconList] %s: UP: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
4535 #endif
4536 break;
4540 active_entry = (struct IconEntry *)(((struct Node *)active_entry)->ln_Pred);
4543 if (!(active_entry))
4545 #if defined(DEBUG_ILC_KEYEVENTS)
4546 D(bug("[IconList] %s: UP: No Next UP Node - Getting Last visible entry ..\n", __PRETTY_FUNCTION__));
4547 #endif
4548 /* We didnt find a "next UP" entry so just use the last visible */
4549 active_entry = Node_LastVisible(&data->icld_IconList);
4552 if (active_entry)
4554 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
4556 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
4557 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4558 data->update_entry = active_entry;
4559 MUI_Redraw(obj, MADF_DRAWUPDATE);
4562 data->icld_FocusIcon = active_entry;
4563 break;
4565 case RAWKEY_DOWN:
4566 rawkey_handled = TRUE;
4568 #if defined(DEBUG_ILC_KEYEVENTS)
4569 D(bug("[IconList] %s: RAWKEY_DOWN\n", __PRETTY_FUNCTION__));
4570 #endif
4571 if (data->icld_FocusIcon)
4573 start_entry = data->icld_FocusIcon;
4574 #if defined(DEBUG_ILC_KEYEVENTS)
4575 D(bug("[IconList] %s: DOWN: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
4576 #endif
4578 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
4579 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4580 data->update_entry = start_entry;
4581 MUI_Redraw(obj, MADF_DRAWUPDATE);
4583 start_X = start_entry->ie_IconX;
4584 start_Y = start_entry->ie_IconY;
4585 #if defined(DEBUG_ILC_KEYEVENTS)
4586 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));
4587 #endif
4588 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4590 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4592 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
4593 #if defined(DEBUG_ILC_KEYEVENTS)
4594 D(bug("[IconList] %s: DOWN: adjusted start_X for grid = %d\n", __PRETTY_FUNCTION__, start_X));
4595 #endif
4599 if ((active_entry = Node_NextVisible(start_entry)) &&
4600 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
4602 #if defined(DEBUG_ILC_KEYEVENTS)
4603 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));
4604 #endif
4605 active_Y = active_entry->ie_IconY;
4607 if (active_Y == start_Y)
4610 #if defined(DEBUG_ILC_KEYEVENTS)
4611 D(bug("[IconList] %s: DOWN: active_entry is on our row (not at the edge)\n", __PRETTY_FUNCTION__));
4612 #endif
4613 entry_next = active_entry;
4614 next_X = entry_next->ie_IconX;
4615 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4617 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4618 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
4622 #if defined(DEBUG_ILC_KEYEVENTS)
4623 D(bug("[IconList] %s: DOWN: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
4624 #endif
4627 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
4629 #if defined(DEBUG_ILC_KEYEVENTS)
4630 D(bug("[IconList] %s: DOWN: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
4631 #endif
4632 DoMethod(obj, MUIM_IconList_UnselectAll);
4635 #if defined(DEBUG_ILC_KEYEVENTS)
4636 D(bug("[IconList] %s: DOWN: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
4637 #endif
4638 if (!(active_entry))
4640 // If nothing is selected we will use the First visible entry ..
4641 active_entry = Node_FirstVisible(&data->icld_IconList);
4642 start_X = active_entry->ie_IconX;
4643 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4645 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4646 start_X = start_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
4648 start_Y = active_entry->ie_IconY;
4651 while (active_entry != NULL)
4653 #if defined(DEBUG_ILC_KEYEVENTS)
4654 D(bug("[IconList] %s: DOWN: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
4655 #endif
4656 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
4658 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4659 break;
4661 else
4663 active_X = active_entry->ie_IconX;
4665 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4667 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4668 x_diff = ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
4670 active_Y = active_entry->ie_IconY;
4672 if (start_entry)
4674 if (entry_next)
4676 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
4677 (active_Y > start_Y) &&
4678 (((active_X - x_diff) >= start_X ) &&
4679 ((active_X - x_diff) <= (start_X + start_entry->ie_AreaWidth + (x_diff*2)))))
4681 #if defined(DEBUG_ILC_KEYEVENTS)
4682 D(bug("[IconList] %s: DOWN: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
4683 #endif
4684 break;
4686 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
4688 #if defined(DEBUG_ILC_KEYEVENTS)
4689 D(bug("[IconList] %s: DOWN: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
4690 #endif
4691 start_X = entry_next->ie_IconX;
4692 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4694 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4695 start_X = start_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
4698 if ((entry_next = (struct IconEntry *)Node_NextVisible(entry_next)))
4700 if (entry_next->ie_IconX < start_X)
4701 entry_next = NULL;
4702 else
4704 next_X = entry_next->ie_IconX;
4705 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4707 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4708 next_X = next_X + ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
4712 start_Y = 0;
4713 #if defined(DEBUG_ILC_KEYEVENTS)
4714 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));
4715 #endif
4716 active_entry = Node_FirstVisible(&data->icld_IconList);
4719 else
4721 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
4722 (active_Y > start_Y) &&
4723 (active_X > start_X - 1))
4725 #if defined(DEBUG_ILC_KEYEVENTS)
4726 D(bug("[IconList] %s: DOWN: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
4727 #endif
4728 break;
4732 else
4734 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4736 #if defined(DEBUG_ILC_KEYEVENTS)
4737 D(bug("[IconList] %s: DOWN: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
4738 #endif
4739 break;
4743 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
4746 if (!(active_entry))
4748 #if defined(DEBUG_ILC_KEYEVENTS)
4749 D(bug("[IconList] %s: DOWN: No Next DOWN Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
4750 #endif
4751 /* We didnt find a "next DOWN" entry so just use the first visible */
4752 active_entry = Node_FirstVisible(&data->icld_IconList);
4755 if (active_entry)
4757 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
4759 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
4760 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4761 data->update_entry = active_entry;
4762 MUI_Redraw(obj, MADF_DRAWUPDATE);
4765 data->icld_FocusIcon = active_entry;
4766 break;
4768 case RAWKEY_LEFT:
4769 rawkey_handled = TRUE;
4771 #if defined(DEBUG_ILC_KEYEVENTS)
4772 D(bug("[IconList] %s: RAWKEY_LEFT\n", __PRETTY_FUNCTION__));
4773 #endif
4774 if (data->icld_FocusIcon)
4776 start_entry = data->icld_FocusIcon;
4777 #if defined(DEBUG_ILC_KEYEVENTS)
4778 D(bug("[IconList] %s: LEFT: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
4779 #endif
4781 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
4782 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4783 data->update_entry = start_entry;
4784 MUI_Redraw(obj, MADF_DRAWUPDATE);
4786 start_X = start_entry->ie_IconX;
4787 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4789 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4790 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
4792 start_Y = start_entry->ie_IconY;
4794 #if defined(DEBUG_ILC_KEYEVENTS)
4795 D(bug("[IconList] %s: LEFT: start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
4796 #endif
4798 if (!(active_entry = Node_NextVisible(start_entry)) && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
4800 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
4801 #if defined(DEBUG_ILC_KEYEVENTS)
4802 D(bug("[IconList] %s: LEFT: Start at the beginning (Active @ 0x%p) using entry X + Width\n", __PRETTY_FUNCTION__, active_entry));
4803 #endif
4804 start_X = start_X + start_entry->ie_AreaWidth;
4805 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4807 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4808 start_X = start_X + ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
4811 start_Y = 0;
4812 entry_next = NULL;
4814 else if (active_entry && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
4816 #if defined(DEBUG_ILC_KEYEVENTS)
4817 D(bug("[IconList] %s: LEFT: Active @ 0x%p, X %d\n", __PRETTY_FUNCTION__, active_entry, active_entry->ie_IconX));
4818 #endif
4819 if ((entry_next = Node_NextVisible(start_entry)))
4821 #if defined(DEBUG_ILC_KEYEVENTS)
4822 D(bug("[IconList] %s: LEFT: Next @ 0x%p, X %d\n", __PRETTY_FUNCTION__, entry_next, entry_next->ie_IconX));
4823 #endif
4825 if (entry_next->ie_IconX < start_X)
4826 entry_next = NULL;
4827 else
4829 next_X = entry_next->ie_IconX;
4830 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4832 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4833 next_X = next_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
4838 #if defined(DEBUG_ILC_KEYEVENTS)
4839 D(bug("[IconList] %s: LEFT: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
4840 #endif
4843 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
4845 #if defined(DEBUG_ILC_KEYEVENTS)
4846 D(bug("[IconList] %s: LEFT: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
4847 #endif
4848 DoMethod(obj, MUIM_IconList_UnselectAll);
4851 #if defined(DEBUG_ILC_KEYEVENTS)
4852 D(bug("[IconList] %s: LEFT: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
4853 #endif
4855 if (!(active_entry))
4857 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
4860 while (active_entry != NULL)
4862 #if defined(DEBUG_ILC_KEYEVENTS)
4863 D(bug("[IconList] %s: LEFT: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
4864 #endif
4865 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
4867 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4868 break;
4870 else
4872 LONG active_entry_X = active_entry->ie_IconX;
4873 LONG active_entry_Y;
4874 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4876 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4877 active_entry_X = active_entry_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
4879 active_entry_Y = active_entry->ie_IconY;
4881 if (start_entry)
4883 if (entry_next)
4885 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
4886 (active_entry_Y > start_Y) &&
4887 ((active_entry_X > start_X - 1) &&
4888 (active_entry_X < next_X)))
4890 #if defined(DEBUG_ILC_KEYEVENTS)
4891 D(bug("[IconList] %s: LEFT: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
4892 #endif
4893 break;
4895 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
4897 #if defined(DEBUG_ILC_KEYEVENTS)
4898 D(bug("[IconList] %s: LEFT: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
4899 #endif
4900 start_X = entry_next->ie_IconX;
4901 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4903 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4904 start_X = start_X - ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
4907 if ((entry_next = Node_NextVisible(entry_next)))
4909 if (entry_next->ie_IconX < start_X)
4910 entry_next = NULL;
4911 else
4913 next_X = entry_next->ie_IconX;
4914 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
4916 if (entry_next->ie_AreaWidth < data->icld_IconAreaLargestWidth)
4917 next_X = next_X + ((data->icld_IconAreaLargestWidth - entry_next->ie_AreaWidth)/2);
4921 start_Y = 0;
4922 #if defined(DEBUG_ILC_KEYEVENTS)
4923 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));
4924 #endif
4925 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
4928 else
4930 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
4931 (active_entry_Y > start_Y) &&
4932 (active_entry_X > start_X - 1))
4934 #if defined(DEBUG_ILC_KEYEVENTS)
4935 D(bug("[IconList] %s: LEFT: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
4936 #endif
4937 break;
4941 else
4943 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
4945 #if defined(DEBUG_ILC_KEYEVENTS)
4946 D(bug("[IconList] %s: LEFT: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
4947 #endif
4948 break;
4952 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
4955 if (!(active_entry))
4957 #if defined(DEBUG_ILC_KEYEVENTS)
4958 D(bug("[IconList] %s: LEFT: No Next LEFT Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
4959 #endif
4960 /* We didnt find a "next LEFT" entry so just use the last visible */
4961 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
4962 while ((active_entry != NULL) &&(!(active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
4964 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
4968 if (active_entry)
4970 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
4972 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
4973 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4974 data->update_entry = active_entry;
4975 MUI_Redraw(obj, MADF_DRAWUPDATE);
4978 data->icld_FocusIcon = active_entry;
4979 break;
4981 case RAWKEY_RIGHT:
4982 rawkey_handled = TRUE;
4984 #if defined(DEBUG_ILC_KEYEVENTS)
4985 D(bug("[IconList] %s: RAWKEY_RIGHT\n", __PRETTY_FUNCTION__));
4986 #endif
4988 if (data->icld_FocusIcon)
4990 start_entry = data->icld_FocusIcon;
4991 #if defined(DEBUG_ILC_KEYEVENTS)
4992 D(bug("[IconList] %s: RIGHT: Clearing existing focused entry @ 0x%p\n", __PRETTY_FUNCTION__, start_entry));
4993 #endif
4994 start_entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
4995 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
4996 data->update_entry = start_entry;
4997 MUI_Redraw(obj, MADF_DRAWUPDATE);
4999 start_X = start_entry->ie_IconX;
5000 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5002 if (start_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5003 start_X = start_X - ((data->icld_IconAreaLargestWidth - start_entry->ie_AreaWidth)/2);
5005 start_Y = start_entry->ie_IconY;
5007 #if defined(DEBUG_ILC_KEYEVENTS)
5008 D(bug("[IconList] %s: RIGHT: start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5009 #endif
5010 if (!(active_entry = Node_NextVisible(start_entry)) && (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)))
5012 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5013 #if defined(DEBUG_ILC_KEYEVENTS)
5014 D(bug("[IconList] %s: RIGHT: Start at the beginning (Active @ 0x%p) using entry X + Width\n", __PRETTY_FUNCTION__, active_entry));
5015 #endif
5016 start_X = 0;
5017 start_Y = start_Y + start_entry->ie_AreaHeight;
5018 entry_next = NULL;
5020 else if (active_entry && (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5022 #if defined(DEBUG_ILC_KEYEVENTS)
5023 D(bug("[IconList] %s: RIGHT: Active @ 0x%p, X %d\n", __PRETTY_FUNCTION__, active_entry, active_entry->ie_IconX));
5024 #endif
5025 if ((entry_next = Node_NextVisible(start_entry)))
5027 #if defined(DEBUG_ILC_KEYEVENTS)
5028 D(bug("[IconList] %s: RIGHT: Next @ 0x%p, X %d\n", __PRETTY_FUNCTION__, entry_next, entry_next->ie_IconX));
5029 #endif
5031 if (entry_next->ie_IconY < start_Y)
5032 entry_next = NULL;
5033 else
5034 next_Y = entry_next->ie_IconY;
5037 #if defined(DEBUG_ILC_KEYEVENTS)
5038 D(bug("[IconList] %s: RIGHT: using start_X %d, start_Y %d\n", __PRETTY_FUNCTION__, start_X, start_Y));
5039 #endif
5042 if (!(message->imsg->Qualifier & IEQUALIFIER_LSHIFT) && ((data->icld_SelectionLastClicked)&&(data->icld_SelectionLastClicked != active_entry)))
5044 #if defined(DEBUG_ILC_KEYEVENTS)
5045 D(bug("[IconList] %s: RIGHT: Clearing selected icons ..\n", __PRETTY_FUNCTION__));
5046 #endif
5047 DoMethod(obj, MUIM_IconList_UnselectAll);
5050 #if defined(DEBUG_ILC_KEYEVENTS)
5051 D(bug("[IconList] %s: RIGHT: active = 0x%p, next = 0x%p\n", __PRETTY_FUNCTION__, active_entry, entry_next));
5052 #endif
5054 if (!(active_entry))
5056 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5059 while (active_entry != NULL)
5061 #if defined(DEBUG_ILC_KEYEVENTS)
5062 D(bug("[IconList] %s: RIGHT: Checking active @ 0x%p\n", __PRETTY_FUNCTION__, active_entry));
5063 #endif
5064 if (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL))
5066 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5067 break;
5069 else
5071 LONG active_entry_X = active_entry->ie_IconX;
5072 LONG active_entry_Y;
5073 if (data->icld__Option_IconListMode == ICON_LISTMODE_GRID)
5075 if (active_entry->ie_AreaWidth < data->icld_IconAreaLargestWidth)
5076 active_entry_X = active_entry_X - ((data->icld_IconAreaLargestWidth - active_entry->ie_AreaWidth)/2);
5078 active_entry_Y = active_entry->ie_IconY;
5080 if (start_entry)
5082 if (entry_next)
5084 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5085 (active_entry_X > start_X) &&
5086 ((active_entry_Y > start_Y - 1) &&
5087 (active_entry_Y < next_Y)))
5089 #if defined(DEBUG_ILC_KEYEVENTS)
5090 D(bug("[IconList] %s: RIGHT: (A) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5091 #endif
5092 break;
5094 else if (active_entry == (struct IconEntry *)GetTail(&data->icld_IconList))
5096 #if defined(DEBUG_ILC_KEYEVENTS)
5097 D(bug("[IconList] %s: RIGHT: (A) reached list end .. starting at the beginng ..\n", __PRETTY_FUNCTION__));
5098 #endif
5099 start_Y = entry_next->ie_IconY;
5101 if ((entry_next = Node_NextVisible(entry_next)))
5103 if (entry_next->ie_IconY < start_Y)
5104 entry_next = NULL;
5105 else
5107 next_Y = entry_next->ie_IconY;
5110 start_Y = 0;
5111 #if defined(DEBUG_ILC_KEYEVENTS)
5112 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));
5113 #endif
5114 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5117 else
5119 if ((active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
5120 (active_entry_X > start_X) &&
5121 (active_entry_Y > start_Y - 1))
5123 #if defined(DEBUG_ILC_KEYEVENTS)
5124 D(bug("[IconList] %s: RIGHT: (B) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5125 #endif
5126 break;
5130 else
5132 if (active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5134 #if defined(DEBUG_ILC_KEYEVENTS)
5135 D(bug("[IconList] %s: RIGHT: (C) entry 0x%p matches\n", __PRETTY_FUNCTION__, active_entry));
5136 #endif
5137 break;
5141 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5144 if (!(active_entry))
5146 #if defined(DEBUG_ILC_KEYEVENTS)
5147 D(bug("[IconList] %s: RIGHT: No Next RIGHT Node - Getting first visable entry ..\n", __PRETTY_FUNCTION__));
5148 #endif
5149 /* We didnt find a "next RIGHT" entry so just use the first visible */
5150 active_entry = (struct IconEntry *)GetHead(&data->icld_IconList);
5151 while ((active_entry != NULL) &&(!(active_entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)))
5153 active_entry = (struct IconEntry *)GetSucc(&active_entry->ie_IconNode);
5157 if (active_entry)
5159 if (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS))
5161 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5162 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5163 data->update_entry = active_entry;
5164 MUI_Redraw(obj, MADF_DRAWUPDATE);
5167 data->icld_FocusIcon = active_entry;
5168 break;
5170 case RAWKEY_HOME:
5171 rawkey_handled = TRUE;
5173 #if defined(DEBUG_ILC_KEYEVENTS)
5174 D(bug("[IconList] %s: RAWKEY_HOME\n", __PRETTY_FUNCTION__));
5175 #endif
5177 if (data->icld_FocusIcon)
5179 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5180 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5181 data->update_entry = data->icld_FocusIcon;
5182 MUI_Redraw(obj, MADF_DRAWUPDATE);
5185 active_entry = Node_FirstVisible(&data->icld_IconList);
5187 if ((active_entry) && (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
5189 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5190 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5191 data->update_entry = active_entry;
5192 MUI_Redraw(obj, MADF_DRAWUPDATE);
5194 data->icld_FocusIcon = active_entry;
5195 break;
5197 case RAWKEY_END:
5198 rawkey_handled = TRUE;
5200 #if defined(DEBUG_ILC_KEYEVENTS)
5201 D(bug("[IconList] %s: RAWKEY_END\n", __PRETTY_FUNCTION__));
5202 #endif
5204 if (data->icld_FocusIcon)
5206 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5207 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5208 data->update_entry = data->icld_FocusIcon;
5209 MUI_Redraw(obj, MADF_DRAWUPDATE);
5212 active_entry = Node_LastVisible(&data->icld_IconList);
5214 if ((active_entry) && (!(active_entry->ie_Flags & ICONENTRY_FLAG_FOCUS)))
5216 active_entry->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5217 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5218 data->update_entry = active_entry;
5219 MUI_Redraw(obj, MADF_DRAWUPDATE);
5221 data->icld_FocusIcon = active_entry;
5222 break;
5225 if (rawkey_handled) return MUI_EventHandlerRC_Eat;
5227 break;
5229 case IDCMP_MOUSEBUTTONS:
5230 #if defined(DEBUG_ILC_EVENTS)
5231 D(bug("[IconList] %s: IDCMP_MOUSEBUTTONS\n", __PRETTY_FUNCTION__));
5232 #endif
5233 if (message->imsg->Code == SELECTDOWN)
5235 /* check if mouse pressed on iconlist area */
5236 if (mx >= 0 && mx < _width(obj) && my >= 0 && my < _height(obj))
5238 BOOL icon_doubleclicked = FALSE;
5239 BOOL update_entry;
5240 struct IconEntry *node = NULL;
5241 struct IconEntry *new_selected = NULL;
5243 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
5245 LONG clickColumn = -1, clickRow = -1;
5247 LONG x = _mleft(obj) - data->icld_ViewX + LINE_SPACING_LEFT;
5248 LONG index, w, i;
5250 for(i = 0; i < NUM_COLUMNS; i++)
5252 index = data->icld_LVMAttribs->lmva_ColumnPos[i];
5254 if (!(data->icld_LVMAttribs->lmva_ColumnFlags[index] & LVMCF_COLVISIBLE)) continue;
5256 w = data->icld_LVMAttribs->lmva_ColumnWidth[index];
5258 if ((mx >= x) && (mx < x + w))
5260 clickColumn = index;
5261 break;
5263 x += w;
5266 if (((data->icld_LVMAttribs->lvma_Flags & LVMAF_NOHEADER) == 0) && (my <= data->icld_LVMAttribs->lmva_HeaderHeight))
5268 data->icld_LVMAttribs->lmva_LastSelectedColumn = clickColumn;
5270 data->icld_UpdateMode = UPDATE_HEADERENTRY;
5271 data->update_entry = clickColumn;
5273 MUI_Redraw(obj, MADF_DRAWUPDATE);
5276 else
5278 LONG current = 0, index = (my - data->icld_LVMAttribs->lmva_HeaderHeight + data->icld_ViewY) / data->icld_LVMAttribs->lmva_RowHeight;
5280 ForeachNode(&data->icld_IconList, node)
5282 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5284 update_entry = FALSE;
5286 if (current == index)
5288 clickRow = current;
5289 new_selected = node;
5291 else
5293 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
5295 if (!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
5297 Remove(&node->ie_SelectionNode);
5298 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
5299 update_entry = TRUE;
5303 if (node->ie_Flags & ICONENTRY_FLAG_FOCUS)
5305 node->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5306 update_entry = TRUE;
5309 if (update_entry)
5311 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5312 data->update_entry = node;
5313 MUI_Redraw(obj, MADF_DRAWUPDATE);
5314 D(bug("[IconList] %s: Rendered entry '%s'\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
5317 current++;
5321 if ((DoubleClick(data->last_secs, data->last_mics, message->imsg->Seconds, message->imsg->Micros)) && (data->icld_SelectionLastClicked == new_selected))
5323 D(bug("[IconList] %s: Entry double-clicked\n", __PRETTY_FUNCTION__));
5324 icon_doubleclicked = TRUE;
5327 if ((new_selected != NULL) && (clickRow != -1) && (clickColumn != -1))
5329 D(bug("[IconList] %s: Clicked on Row %d Column %d ..\n", __PRETTY_FUNCTION__, clickRow, clickColumn));
5331 data->icld_LassoActive = FALSE;
5332 update_entry = FALSE;
5334 if (!(new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED))
5336 AddTail(&data->icld_SelectionList, &new_selected->ie_SelectionNode);
5337 new_selected->ie_Flags |= ICONENTRY_FLAG_SELECTED;
5338 update_entry = TRUE;
5340 if (!(new_selected->ie_Flags & ICONENTRY_FLAG_FOCUS))
5342 new_selected->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5343 data->icld_FocusIcon = new_selected;
5346 else if ((icon_doubleclicked == FALSE) && (message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
5348 Remove(&new_selected->ie_SelectionNode);
5349 new_selected->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
5350 update_entry = TRUE;
5353 if (update_entry)
5355 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5356 data->update_entry = new_selected;
5357 MUI_Redraw(obj, MADF_DRAWUPDATE);
5358 D(bug("[IconList] %s: Rendered 'new_selected' entry '%s'\n", __PRETTY_FUNCTION__, new_selected->ie_IconListEntry.label));
5361 else
5363 struct Window * thisWindow = NULL;
5364 #if defined(DEBUG_ILC_EVENTS) && defined(DEBUG_ILC_LASSO)
5365 D(bug("[IconList] %s: Starting Lasso\n", __PRETTY_FUNCTION__));
5366 #endif
5367 /* No entry clicked on ... Start Lasso-selection */
5368 data->icld_LassoActive = TRUE;
5369 if (!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
5371 data->icld_SelectionLastClicked = NULL;
5372 data->icld_FocusIcon = NULL;
5374 data->icld_LassoRectangle.MinX = mx - data->view_rect.MinX + data->icld_ViewX;
5375 data->icld_LassoRectangle.MinY = my - data->view_rect.MinY + data->icld_ViewY;
5376 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
5377 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
5379 /* Draw initial Lasso frame */
5380 IconList_InvertLassoOutlines(obj, data, &data->icld_LassoRectangle);
5382 GET(obj, MUIA_Window, &thisWindow);
5383 if (thisWindow)
5385 ModifyIDCMP(thisWindow, (thisWindow->IDCMPFlags|IDCMP_INTUITICKS));
5386 if (!(data->ehn.ehn_Events & IDCMP_INTUITICKS))
5388 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
5389 data->ehn.ehn_Events |= IDCMP_INTUITICKS;
5390 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
5396 else
5398 struct Rectangle rect;
5400 /* check if clicked on entry */
5401 #if defined(__AROS__)
5402 ForeachNode(&data->icld_IconList, node)
5403 #else
5404 Foreach_Node(&data->icld_IconList, node);
5405 #endif
5407 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5409 update_entry = FALSE;
5411 rect.MinX = node->ie_IconX;
5412 rect.MaxX = node->ie_IconX + node->ie_AreaWidth - 1;
5413 rect.MinY = node->ie_IconY;
5414 rect.MaxY = node->ie_IconY + node->ie_AreaHeight - 1;
5416 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
5417 (node->ie_AreaWidth < data->icld_IconAreaLargestWidth))
5419 rect.MinX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
5420 rect.MaxX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
5423 if ((((mx + data->icld_ViewX) >= rect.MinX) && ((mx + data->icld_ViewX) <= rect.MaxX )) &&
5424 (((my + data->icld_ViewY) >= rect.MinY) && ((my + data->icld_ViewY) <= rect.MaxY )) &&
5425 !new_selected)
5427 new_selected = node;
5428 #if defined(DEBUG_ILC_EVENTS)
5429 D(bug("[IconList] %s: Entry '%s' clicked on ..\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
5430 #endif
5433 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
5435 if ((new_selected != node) &&
5436 (!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))))
5438 Remove(&node->ie_SelectionNode);
5439 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
5440 update_entry = TRUE;
5444 if ((node->ie_Flags & ICONENTRY_FLAG_FOCUS) && (new_selected != node))
5446 node->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
5447 update_entry = TRUE;
5450 if (update_entry)
5452 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5453 data->update_entry = node;
5454 MUI_Redraw(obj, MADF_DRAWUPDATE);
5455 #if defined(DEBUG_ILC_EVENTS)
5456 D(bug("[IconList] %s: Rendered entry '%s'\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
5457 #endif
5462 if ((DoubleClick(data->last_secs, data->last_mics, message->imsg->Seconds, message->imsg->Micros)) && (data->icld_SelectionLastClicked == new_selected))
5464 #if defined(DEBUG_ILC_EVENTS)
5465 D(bug("[IconList] %s: Entry double-clicked\n", __PRETTY_FUNCTION__));
5466 #endif
5467 icon_doubleclicked = TRUE;
5470 if (new_selected != NULL)
5472 data->icld_LassoActive = FALSE;
5473 update_entry = FALSE;
5475 if (!(new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED))
5477 AddTail(&data->icld_SelectionList, &new_selected->ie_SelectionNode);
5478 new_selected->ie_Flags |= ICONENTRY_FLAG_SELECTED;
5479 update_entry = TRUE;
5481 if (!(new_selected->ie_Flags & ICONENTRY_FLAG_FOCUS))
5483 new_selected->ie_Flags |= ICONENTRY_FLAG_FOCUS;
5484 data->icld_FocusIcon = new_selected;
5487 else if ((icon_doubleclicked == FALSE) && (message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
5489 Remove(&new_selected->ie_SelectionNode);
5490 new_selected->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
5491 update_entry = TRUE;
5494 if (update_entry != NULL)
5496 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5497 data->update_entry = new_selected;
5498 MUI_Redraw(obj, MADF_DRAWUPDATE);
5499 #if defined(DEBUG_ILC_EVENTS)
5500 D(bug("[IconList] %s: Rendered 'new_selected' entry '%s'\n", __PRETTY_FUNCTION__, new_selected->ie_IconListEntry.label));
5501 #endif
5504 else
5506 struct Window * thisWindow = NULL;
5507 #if defined(DEBUG_ILC_EVENTS) && defined(DEBUG_ILC_LASSO)
5508 D(bug("[IconList] %s: Starting Lasso\n", __PRETTY_FUNCTION__));
5509 #endif
5510 /* No entry clicked on ... Start Lasso-selection */
5511 data->icld_LassoActive = TRUE;
5512 if (!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))
5514 data->icld_SelectionLastClicked = NULL;
5515 data->icld_FocusIcon = NULL;
5517 data->icld_LassoRectangle.MinX = mx - data->view_rect.MinX + data->icld_ViewX;
5518 data->icld_LassoRectangle.MinY = my - data->view_rect.MinY + data->icld_ViewY;
5519 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
5520 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
5522 /* Draw initial Lasso frame */
5523 IconList_InvertLassoOutlines(obj, data, &data->icld_LassoRectangle);
5525 GET(obj, MUIA_Window, &thisWindow);
5526 if (thisWindow)
5528 ModifyIDCMP(thisWindow, (thisWindow->IDCMPFlags|IDCMP_INTUITICKS));
5529 if (!(data->ehn.ehn_Events & IDCMP_INTUITICKS))
5531 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
5532 data->ehn.ehn_Events |= IDCMP_INTUITICKS;
5533 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
5539 if (new_selected && (new_selected->ie_Flags & ICONENTRY_FLAG_SELECTED))
5540 data->icld_SelectionLastClicked = new_selected;
5541 else
5542 data->icld_SelectionLastClicked = NULL;
5544 data->click_x = mx;
5545 data->click_y = my;
5547 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
5549 data->icld_ClickEvent.shift = !!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT));
5550 data->icld_ClickEvent.entry = data->icld_SelectionLastClicked ? &data->icld_SelectionLastClicked->ie_IconListEntry : NULL;
5551 SET(obj, MUIA_IconList_Clicked, (IPTR)&data->icld_ClickEvent);
5553 if (icon_doubleclicked)
5555 SET(obj, MUIA_IconList_DoubleClick, TRUE);
5557 else if (!data->mouse_pressed)
5559 data->last_secs = message->imsg->Seconds;
5560 data->last_mics = message->imsg->Micros;
5562 /* After a double click you often open a new window
5563 * and since Zune doesn't not support the faking
5564 * of SELECTUP events only change the Events
5565 * if not doubleclicked */
5567 data->mouse_pressed |= LEFT_BUTTON;
5569 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
5571 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
5572 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
5573 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
5577 return MUI_EventHandlerRC_Eat;
5580 else if (message->imsg->Code == MIDDLEDOWN)
5582 if (!data->mouse_pressed)
5584 data->mouse_pressed |= MIDDLE_BUTTON;
5586 data->click_x = data->icld_ViewX + mx;
5587 data->click_y = data->icld_ViewY + my;
5589 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
5591 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
5592 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
5593 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
5597 else
5599 if (message->imsg->Code == SELECTUP)
5601 if (data->icld_LassoActive == TRUE)
5603 #if defined(DEBUG_ILC_EVENTS) && defined(DEBUG_ILC_LASSO)
5604 D(bug("[IconList] %s: Removing Lasso\n", __PRETTY_FUNCTION__));
5605 #endif
5606 // End Lasso-selection
5607 struct Rectangle old_lasso;
5608 struct IconEntry *node = NULL;
5609 struct Window *thisWindow = NULL;
5611 GET(obj, MUIA_Window, &thisWindow);
5612 if (thisWindow)
5614 ModifyIDCMP(thisWindow, (thisWindow->IDCMPFlags & ~(IDCMP_INTUITICKS)));
5615 if ((data->ehn.ehn_Events & IDCMP_INTUITICKS))
5617 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
5618 data->ehn.ehn_Events &= ~IDCMP_INTUITICKS;
5619 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
5622 //Clear Lasso Frame..
5623 GetAbsoluteLassoRect(data, &old_lasso);
5624 IconList_InvertLassoOutlines(obj, data, &old_lasso);
5626 data->icld_LassoActive = FALSE;
5628 //Remove Lasso flag from affected icons..
5629 #if defined(__AROS__)
5630 ForeachNode(&data->icld_IconList, node)
5631 #else
5632 Foreach_Node(&data->icld_IconList, node);
5633 #endif
5635 if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
5637 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
5640 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
5642 else if (data->icld_LVMAttribs->lmva_LastSelectedColumn != -1)
5644 ULONG orig_sortflags = data->icld_SortFlags;
5646 if (data->icld_LVMAttribs->lmva_SortColumn == data->icld_LVMAttribs->lmva_LastSelectedColumn)
5648 if (data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
5649 data->icld_SortFlags &= ~MUIV_IconList_Sort_Reverse;
5650 else
5651 data->icld_SortFlags |= MUIV_IconList_Sort_Reverse;
5654 switch (data->icld_LVMAttribs->lmva_LastSelectedColumn)
5656 case INDEX_NAME:
5657 data->icld_SortFlags &= ~MUIV_IconList_Sort_MASK;
5658 data->icld_SortFlags |= MUIV_IconList_Sort_ByName;
5659 break;
5661 case INDEX_SIZE:
5662 data->icld_SortFlags &= ~MUIV_IconList_Sort_MASK;
5663 data->icld_SortFlags |= MUIV_IconList_Sort_BySize;
5664 break;
5666 case INDEX_DATE:
5667 data->icld_SortFlags &= ~MUIV_IconList_Sort_MASK;
5668 data->icld_SortFlags |= MUIV_IconList_Sort_ByDate;
5669 break;
5672 if (orig_sortflags != data->icld_SortFlags)
5674 data->icld_LVMAttribs->lmva_SortColumn = data->icld_LVMAttribs->lmva_LastSelectedColumn;
5676 data->icld_LVMAttribs->lmva_LastSelectedColumn = -1;
5678 DoMethod(obj, MUIM_IconList_Sort);
5682 data->mouse_pressed &= ~LEFT_BUTTON;
5685 if (message->imsg->Code == MIDDLEUP)
5687 data->mouse_pressed &= ~MIDDLE_BUTTON;
5690 if ((data->ehn.ehn_Events & IDCMP_MOUSEMOVE) && !data->mouse_pressed)
5692 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
5693 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
5694 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
5697 break;
5699 case IDCMP_INTUITICKS:
5701 #if defined(DEBUG_ILC_EVENTS)
5702 D(bug("[IconList] %s: IDCMP_INTUITICKS (%d, %d)\n", __PRETTY_FUNCTION__, mx, my));
5703 #endif
5704 if ((data->icld_LassoActive == FALSE)||(!(data->mouse_pressed & LEFT_BUTTON)))
5706 break;
5708 if (((mx >= 0) && (mx <= _mwidth(obj))) &&
5709 ((my >= 0) && (my <= _mheight(obj))))
5710 break;
5713 case IDCMP_MOUSEMOVE:
5714 #if defined(DEBUG_ILC_EVENTS)
5715 D(bug("[IconList] %s: IDCMP_MOUSEMOVE\n", __PRETTY_FUNCTION__));
5716 #endif
5717 if (data->mouse_pressed & LEFT_BUTTON)
5719 LONG move_x = mx;
5720 LONG move_y = my;
5722 if (data->icld_SelectionLastClicked && (data->icld_LassoActive == FALSE) &&
5723 ((abs(move_x - data->click_x) >= 2) || (abs(move_y - data->click_y) >= 2)))
5725 // Entry(s) being dragged ....
5726 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
5727 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
5728 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
5730 data->mouse_pressed &= ~LEFT_BUTTON;
5732 data->touch_x = move_x + data->icld_ViewX - data->icld_SelectionLastClicked->ie_IconX;
5733 data->touch_y = move_y + data->icld_ViewY - data->icld_SelectionLastClicked->ie_IconY;
5734 DoMethod(obj,MUIM_DoDrag, data->touch_x, data->touch_y, 0);
5736 else if (data->icld_LassoActive == TRUE)
5738 #if defined(DEBUG_ILC_EVENTS) && defined(DEBUG_ILC_LASSO)
5739 D(bug("[IconList] %s: Update Lasso\n", __PRETTY_FUNCTION__));
5740 #endif
5741 //Lasso active ..
5742 struct Rectangle new_lasso,
5743 old_lasso;
5744 struct Rectangle iconrect;
5746 struct IconEntry *node = NULL;
5747 // struct IconEntry *new_selected = NULL;
5749 /* Remove previous Lasso frame */
5750 GetAbsoluteLassoRect(data, &old_lasso);
5751 IconList_InvertLassoOutlines(obj, data, &old_lasso);
5753 /* if the mouse leaves our visible area scroll the view */
5754 if (mx < 0 || mx >= _mwidth(obj) || my < 0 || my >= _mheight(obj))
5756 LONG newleft = data->icld_ViewX;
5757 LONG newtop = data->icld_ViewY;
5759 if (mx >= _mwidth(obj)) newleft += (mx - _mwidth(obj));
5760 else if (mx < 0) newleft += mx;
5761 if (my >= _mheight(obj)) newtop += (my - _mheight(obj));
5762 else if (my < 0) newtop += my;
5764 if (newleft + _mwidth(obj) > data->icld_AreaWidth) newleft = data->icld_AreaWidth - _mwidth(obj);
5765 if (newleft < 0) newleft = 0;
5767 if (newtop + _mheight(obj) > data->icld_AreaHeight) newtop = data->icld_AreaHeight - _mheight(obj);
5768 if (newtop < 0) newtop = 0;
5770 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
5772 SetAttrs(obj, MUIA_Virtgroup_Left, newleft, MUIA_Virtgroup_Top, newtop, TAG_DONE);
5776 /* update Lasso coordinates */
5777 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
5778 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
5780 /* get absolute Lasso coordinates */
5781 GetAbsoluteLassoRect(data, &new_lasso);
5783 LONG current = 0, startIndex = 0, endIndex = 0;
5785 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
5787 LONG minY = data->icld_LassoRectangle.MinY,
5788 maxY = data->icld_LassoRectangle.MaxY;
5790 if (minY > maxY)
5792 minY ^= maxY;
5793 maxY ^= minY;
5794 minY ^= maxY;
5797 startIndex = ((minY + 1) - data->icld_LVMAttribs->lmva_HeaderHeight) / data->icld_LVMAttribs->lmva_RowHeight;
5798 endIndex = ((maxY - 1) - data->icld_LVMAttribs->lmva_HeaderHeight) / data->icld_LVMAttribs->lmva_RowHeight;
5801 #if defined(__AROS__)
5802 ForeachNode(&data->icld_IconList, node)
5803 #else
5804 Foreach_Node(&data->icld_IconList, node);
5805 #endif
5807 IPTR update_entry = (IPTR)NULL;
5809 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
5811 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5813 update_entry = FALSE;
5815 if ((current >= startIndex) && (current <= endIndex))
5817 //Entry is inside our lasso ..
5818 if (!(node->ie_Flags & ICONENTRY_FLAG_LASSO))
5820 /* check if entry was already selected before */
5821 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
5823 Remove(&node->ie_SelectionNode);
5824 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
5826 else
5828 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
5829 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
5831 node->ie_Flags |= ICONENTRY_FLAG_LASSO;
5832 update_entry = (IPTR)node;
5835 else if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
5837 //Entry is no longer inside our lasso - revert its selected state
5838 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
5840 Remove(&node->ie_SelectionNode);
5841 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
5843 else
5845 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
5846 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
5848 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
5849 update_entry = (IPTR)node;
5852 current++;
5855 else
5857 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5859 iconrect.MinX = node->ie_IconX;
5860 iconrect.MaxX = node->ie_IconX + node->ie_AreaWidth - 1;
5861 iconrect.MinY = node->ie_IconY;
5862 iconrect.MaxY = node->ie_IconY + node->ie_AreaHeight - 1;
5863 if ((data->icld__Option_IconListMode == ICON_LISTMODE_GRID) &&
5864 (node->ie_AreaWidth < data->icld_IconAreaLargestWidth))
5866 iconrect.MinX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
5867 iconrect.MaxX += ((data->icld_IconAreaLargestWidth - node->ie_AreaWidth)/2);
5870 if ((((new_lasso.MaxX + data->icld_ViewX) >= iconrect.MinX) && ((new_lasso.MinX + data->icld_ViewX) <= iconrect.MaxX)) &&
5871 (((new_lasso.MaxY + data->icld_ViewY) >= iconrect.MinY) && ((new_lasso.MinY + data->icld_ViewY) <= iconrect.MaxY)))
5873 //Entry is inside our lasso ..
5874 if (!(node->ie_Flags & ICONENTRY_FLAG_LASSO))
5876 /* check if entry was already selected before */
5877 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
5879 Remove(&node->ie_SelectionNode);
5880 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
5882 else
5884 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
5885 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
5887 node->ie_Flags |= ICONENTRY_FLAG_LASSO;
5888 update_entry = (IPTR)node;
5891 else if (node->ie_Flags & ICONENTRY_FLAG_LASSO)
5893 //Entry is no longer inside our lasso - revert its selected state
5894 if (node->ie_Flags & ICONENTRY_FLAG_SELECTED)
5896 Remove(&node->ie_SelectionNode);
5897 node->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
5899 else
5901 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
5902 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
5904 node->ie_Flags &= ~ICONENTRY_FLAG_LASSO;
5905 update_entry = (IPTR)node;
5909 if (update_entry)
5911 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
5912 data->update_entry = (struct IconEntry *)update_entry;
5913 MUI_Redraw(obj, MADF_DRAWUPDATE);
5916 /* Draw Lasso frame */
5917 IconList_InvertLassoOutlines(obj, data, &new_lasso);
5920 return MUI_EventHandlerRC_Eat;
5922 else if (data->mouse_pressed & MIDDLE_BUTTON)
5924 LONG newleft,
5925 newtop;
5927 newleft = data->click_x - mx;
5928 newtop = data->click_y - my;
5930 if (newleft + _mwidth(obj) > data->icld_AreaWidth) newleft = data->icld_AreaWidth - _mwidth(obj);
5931 if (newleft < 0) newleft = 0;
5933 if (newtop + _mheight(obj) > data->icld_AreaHeight) newtop = data->icld_AreaHeight - _mheight(obj);
5934 if (newtop < 0) newtop = 0;
5936 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
5938 SetAttrs(obj, MUIA_Virtgroup_Left, newleft,
5939 MUIA_Virtgroup_Top, newtop,
5940 TAG_DONE);
5943 return MUI_EventHandlerRC_Eat;
5946 break;
5950 return 0;
5954 ///MUIM_IconList_NextIcon()
5955 /**************************************************************************
5956 MUIM_IconList_NextIcon
5957 **************************************************************************/
5958 IPTR IconList__MUIM_IconList_NextIcon(struct IClass *CLASS, Object *obj, struct MUIP_IconList_NextIcon *message)
5960 struct IconList_DATA *data = INST_DATA(CLASS, obj);
5961 struct IconEntry *node = NULL;
5962 struct IconList_Entry *ent = NULL;
5963 IPTR node_successor = (IPTR)NULL;
5965 if (message->entry == NULL) return (IPTR)NULL;
5966 ent = *message->entry;
5968 #if defined(DEBUG_ILC_FUNCS)
5969 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
5970 #endif
5972 if ((IPTR)ent == (IPTR)MUIV_IconList_NextIcon_Start)
5974 D(bug("[IconList] %s: Finding First Entry ..\n", __PRETTY_FUNCTION__));
5975 if (message->nextflag == MUIV_IconList_NextIcon_Selected)
5977 node = (struct IconEntry *)GetHead(&data->icld_SelectionList);
5978 if (node != NULL)
5980 node = (struct IconEntry *)((IPTR)node - ((IPTR)&node->ie_SelectionNode - (IPTR)node));
5983 else if (message->nextflag == MUIV_IconList_NextIcon_Visible)
5985 node = (struct IconEntry *)GetHead(&data->icld_IconList);
5986 while (node != NULL)
5988 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
5989 break;
5991 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
5995 else if ((IPTR)ent != (IPTR)MUIV_IconList_NextIcon_End)
5997 node = (struct IconEntry *)((IPTR)ent - ((IPTR)&node->ie_IconListEntry - (IPTR)node));
5998 if (message->nextflag == MUIV_IconList_NextIcon_Selected)
6000 node_successor = (IPTR)GetSucc(&node->ie_SelectionNode);
6001 if (node_successor != (IPTR)NULL)
6002 node = (struct IconEntry *)((IPTR)node_successor - ((IPTR)&node->ie_SelectionNode - (IPTR)node));
6003 else
6005 D(bug("[IconList] %s: GetSucc() == NULL\n", __PRETTY_FUNCTION__));
6006 node = NULL;
6009 else if (message->nextflag == MUIV_IconList_NextIcon_Visible)
6011 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6012 while (node != NULL)
6014 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6015 break;
6017 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6022 if (node == NULL)
6024 D(bug("[IconList] %s: Returning MUIV_IconList_NextIcon_End\n", __PRETTY_FUNCTION__));
6026 *message->entry = (struct IconList_Entry *)MUIV_IconList_NextIcon_End;
6028 else
6030 D(bug("[IconList] %s: Returning entry for '%s'\n", __PRETTY_FUNCTION__, node->ie_IconListEntry.label));
6032 *message->entry = &node->ie_IconListEntry;
6035 return (IPTR)NULL;
6039 ///MUIM_IconList_GetIconPrivate()
6040 /**************************************************************************
6041 MUIM_IconList_GetIconPrivate
6042 **************************************************************************/
6043 IPTR IconList__MUIM_IconList_GetIconPrivate(struct IClass *CLASS, Object *obj, struct MUIP_IconList_GetIconPrivate *message)
6045 // struct IconList_DATA *data = INST_DATA(CLASS, obj);
6046 struct IconEntry *node = NULL;
6048 if (message->entry == NULL) return (IPTR)NULL;
6050 node = (struct IconEntry *)((IPTR)message->entry - ((IPTR)&node->ie_IconListEntry - (IPTR)node));
6052 return (IPTR)node;
6055 ///MUIM_CreateDragImage()
6056 /**************************************************************************
6057 MUIM_CreateDragImage
6058 **************************************************************************/
6059 IPTR IconList__MUIM_CreateDragImage(struct IClass *CLASS, Object *obj, struct MUIP_CreateDragImage *message)
6061 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6062 struct MUI_DragImage *img = NULL;
6063 LONG first_x = -1,
6064 first_y = -1;
6066 #if defined(DEBUG_ILC_FUNCS)
6067 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6068 #endif
6070 if (!(data->icld_SelectionLastClicked))
6071 DoSuperMethodA(CLASS, obj, (Msg)message);
6073 if ((img = (struct MUI_DragImage *)AllocVec(sizeof(struct MUIP_CreateDragImage), MEMF_CLEAR)))
6075 struct Node *node = NULL;
6076 struct IconEntry *entry = NULL;
6078 LONG depth = GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH);
6080 #if defined(CREATE_FULL_DRAGIMAGE)
6081 #if defined(__AROS__)
6082 ForeachNode(&data->icld_SelectionList, node)
6083 #else
6084 Foreach_Node(&data->icld_SelectionList, node);
6085 #endif
6087 entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
6088 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) && (entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
6090 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) != ICONLIST_DISP_MODELIST)
6092 if ((first_x == -1) || ((first_x != -1) && (entry->ie_IconX < first_x))) first_x = entry->ie_IconX;
6093 if ((first_y == -1) || ((first_y != -1) && (entry->ie_IconY < first_y))) first_y = entry->ie_IconY;
6094 if ((entry->ie_IconX + entry->ie_IconWidth) > img->width) img->width = entry->ie_IconX + entry->ie_IconWidth;
6095 if ((entry->ie_IconY + entry->ie_IconHeight) > img->height) img->height = entry->ie_IconY + entry->ie_IconHeight;
6097 else
6099 img->height += data->icld_LVMAttribs->lmva_RowHeight;
6103 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6105 first_x = 0;
6106 first_y = 0;
6107 img->width = _mright(obj) - _mleft(obj);
6109 else
6110 img->width = (img->width - first_x) + 2;
6112 img->height = (img->height - first_y) + 2;
6113 #else
6114 entry = data->icld_SelectionLastClicked;
6115 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6117 img->width = _mright(obj) - _mleft(obj);
6118 img->height = data->icld_LVMAttribs->lmva_RowHeight;
6119 first_x = 0;
6120 first_y = 0;
6122 else
6124 img->width = entry->ie_IconWidth;
6125 img->height = entry->ie_IconHeight;
6126 first_x = entry->ie_IconX;
6127 first_y = entry->ie_IconY;
6129 #endif
6131 img->touchx = data->click_x - first_x;
6132 img->touchy = data->click_y - first_y;
6134 if ((img->bm = AllocBitMap(img->width, img->height, depth, BMF_CLEAR, _screen(obj)->RastPort.BitMap)))
6136 struct RastPort temprp;
6137 InitRastPort(&temprp);
6138 temprp.BitMap = img->bm;
6140 #if defined(CREATE_FULL_DRAGIMAGE)
6141 ForeachNode(&data->icld_SelectionList, node)
6143 entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
6144 if ((entry->ie_Flags & ICONENTRY_FLAG_VISIBLE) && (entry->ie_Flags & ICONENTRY_FLAG_SELECTED))
6146 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6149 else
6151 DrawIconStateA
6153 &temprp, entry->ie_DiskObj, NULL,
6154 (entry->ie_IconX + 1) - first_x, (entry->ie_IconY + 1) - first_y,
6155 IDS_SELECTED,
6156 __iconList_DrawIconStateTags
6161 #else
6162 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6164 SetABPenDrMd(&temprp, _pens(obj)[MPEN_SHINE], 0, JAM1);
6165 RectFill(&temprp, 0, 0, img->width, img->height);
6167 else
6169 DrawIconStateA
6171 &temprp, entry->ie_DiskObj, NULL,
6172 0, 0,
6173 IDS_SELECTED,
6174 __iconList_DrawIconStateTags
6177 #endif
6178 RastPortSetAlpha(&temprp, data->click_x, data->click_y, img->width, img->height, 0x80, RPALPHAFLAT);
6179 DeinitRastPort(&temprp);
6182 img->touchx = message->touchx;
6183 img->touchy = message->touchy;
6185 img->flags = 0;
6186 #if defined(__MORPHOS__)
6187 img->dragmode = DD_TRANSPARENT;
6188 #endif
6190 return (IPTR)img;
6194 ///MUIM_DeleteDragImage()
6195 /**************************************************************************
6196 MUIM_DeleteDragImage
6197 **************************************************************************/
6198 IPTR IconList__MUIM_DeleteDragImage(struct IClass *CLASS, Object *obj, struct MUIP_DeleteDragImage *message)
6200 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6202 #if defined(DEBUG_ILC_FUNCS)
6203 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6204 #endif
6206 if (!(data->icld_SelectionLastClicked)) return DoSuperMethodA(CLASS,obj,(Msg)message);
6208 if (message->di)
6210 if (message->di->bm)
6211 FreeBitMap(message->di->bm);
6212 FreeVec(message->di);
6214 return (IPTR)NULL;
6218 ///MUIM_DragQuery()
6219 /**************************************************************************
6220 MUIM_DragQuery
6221 **************************************************************************/
6222 IPTR IconList__MUIM_DragQuery(struct IClass *CLASS, Object *obj, struct MUIP_DragQuery *message)
6224 #if defined(DEBUG_ILC_FUNCS)
6225 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6226 #endif
6228 #warning "TODO: highlight the possible drop target entry .."
6230 if (message->obj == obj)
6231 return MUIV_DragQuery_Accept;
6232 else
6234 BOOL is_iconlist = FALSE;
6235 struct IClass *msg_cl = OCLASS(message->obj);
6237 while (msg_cl)
6239 if (msg_cl == CLASS)
6241 is_iconlist = TRUE;
6242 break;
6244 msg_cl = msg_cl->cl_Super;
6246 if (is_iconlist)
6247 return MUIV_DragQuery_Accept;
6250 return MUIV_DragQuery_Refuse;
6254 ///MUIM_DragDrop()
6255 /**************************************************************************
6256 MUIM_DragDrop
6257 **************************************************************************/
6258 IPTR IconList__MUIM_DragDrop(struct IClass *CLASS, Object *obj, struct MUIP_DragDrop *message)
6260 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6262 #if defined(DEBUG_ILC_FUNCS)
6263 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6264 #endif
6266 struct IconList_Entry *entry = (IPTR)MUIV_IconList_NextIcon_Start;
6268 if (data->icld_DragDropEvent)
6270 struct IconList_Drop_SourceEntry *clean_node;
6271 #if defined(DEBUG_ILC_ICONDRAGDROP)
6272 D(bug("[IconList] %s: Cleaning existing IconList_Drop_Event @ %p\n", __PRETTY_FUNCTION__, data->icld_DragDropEvent));
6273 #endif
6274 while ((clean_node = (struct IconList_Drop_SourceEntry *)RemTail(&data->icld_DragDropEvent->drop_SourceList)) != NULL)
6276 FreeVec(clean_node->dropse_Node.ln_Name);
6277 FreeMem(clean_node, sizeof(struct IconList_Drop_SourceEntry));
6279 if (data->icld_DragDropEvent->drop_TargetPath) FreeVec(data->icld_DragDropEvent->drop_TargetPath);
6280 FreeMem(data->icld_DragDropEvent, sizeof(struct IconList_Drop_Event));
6281 data->icld_DragDropEvent = NULL;
6284 /* SANITY CHECK: Get first selected entry from SOURCE iconlist */
6285 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
6287 if ((entry) && (entry != (IPTR)MUIV_IconList_NextIcon_End))
6289 /* Ok.. atleast one entry was dropped .. */
6290 char tmp_dirbuff[256];
6291 BPTR tmp_dirlock = (BPTR) NULL;
6293 BOOL iconMove = FALSE;
6294 struct IconEntry *node = NULL;
6295 struct IconEntry *drop_target_node = NULL;
6296 STRPTR directory_path = NULL;
6297 struct IconList_Drop_Event *dragDropEvent = NULL;
6299 GET(obj, MUIA_IconDrawerList_Drawer, &directory_path);
6301 /* Properly expand the name incase it uses devices rather than volumes */
6302 if (directory_path != NULL)
6304 tmp_dirlock = Lock(directory_path, SHARED_LOCK);
6305 if (tmp_dirlock)
6307 if (NameFromLock(tmp_dirlock, tmp_dirbuff, 256) != 0)
6309 directory_path = tmp_dirbuff;
6311 UnLock(tmp_dirlock);
6314 if ((dragDropEvent = AllocMem(sizeof(struct IconList_Drop_Event), MEMF_CLEAR)) == NULL)
6316 #if defined(DEBUG_ILC_ICONDRAGDROP)
6317 D(bug("[IconList] %s: Failed to allocate IconList_Drop_Event Storage!\n", __PRETTY_FUNCTION__));
6318 #endif
6319 goto dragdropdone;
6321 D(bug("[IconList] %s: Allocated IconList_Drop_Event @ %p\n", __PRETTY_FUNCTION__, dragDropEvent));
6323 NewList(&dragDropEvent->drop_SourceList);
6325 /* go through list and check if dropped on entry */
6326 int rowCount = 0;
6328 #if defined(__AROS__)
6329 ForeachNode(&data->icld_IconList, node)
6330 #else
6331 Foreach_Node(&data->icld_IconList, node);
6332 #endif
6334 if ((data->icld_DisplayFlags & ICONLIST_DISP_MODELIST) == ICONLIST_DISP_MODELIST)
6336 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6338 ULONG rowTop = _mtop(obj) + (rowCount * data->icld_LVMAttribs->lmva_RowHeight);
6339 rowTop += data->icld_LVMAttribs->lmva_HeaderHeight;
6341 if (((message->x > _mleft(obj)) && (message->x < _mright(obj)))
6342 && ((message->y > rowTop) && (message->y < (rowTop + data->icld_LVMAttribs->lmva_RowHeight))))
6344 drop_target_node = node;
6345 break;
6348 rowCount++;
6351 else
6353 struct Rectangle iconbox;
6354 LONG click_x = message->x - _mleft(obj);
6355 LONG click_y = message->y - _mtop(obj);
6356 iconbox.MinX = node->ie_IconX - data->icld_ViewX;
6357 iconbox.MaxX = (node->ie_IconX + node->ie_AreaWidth) - data->icld_ViewX;
6358 iconbox.MinY = node->ie_IconY - data->icld_ViewY;
6359 iconbox.MaxY = (node->ie_IconY + node->ie_AreaHeight)- data->icld_ViewY;
6361 if ((node->ie_Flags & ICONENTRY_FLAG_VISIBLE) &&
6362 (click_x >= iconbox.MinX) &&
6363 (click_x < iconbox.MaxX) &&
6364 (click_y >= iconbox.MinY) &&
6365 (click_y < iconbox.MaxY))
6367 drop_target_node = node;
6368 break;
6373 if ((drop_target_node != NULL) &&
6374 ((drop_target_node->ie_IconListEntry.type == ST_SOFTLINK) ||
6375 (drop_target_node->ie_IconListEntry.type == ST_ROOT) ||
6376 (drop_target_node->ie_IconListEntry.type == ST_USERDIR) ||
6377 (drop_target_node->ie_IconListEntry.type == ST_LINKDIR) ||
6378 (drop_target_node->ie_IconListEntry.type == ST_FILE) ||
6379 (drop_target_node->ie_IconListEntry.type == ST_LINKFILE)))
6381 if ((drop_target_node->ie_IconListEntry.type != ST_ROOT) && (drop_target_node->ie_IconListEntry.type != ST_SOFTLINK))
6383 if (directory_path)
6385 int fulllen = strlen(directory_path) + strlen(drop_target_node->ie_IconListEntry.label) + 2;
6387 if ((dragDropEvent->drop_TargetPath = AllocVec(fulllen, MEMF_CLEAR)) == NULL)
6389 bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__);
6390 goto dragdropdone;
6392 strcpy(dragDropEvent->drop_TargetPath, directory_path);
6393 AddPart(dragDropEvent->drop_TargetPath, drop_target_node->ie_IconListEntry.label, fulllen);
6396 else
6398 if ((dragDropEvent->drop_TargetPath = AllocVec(strlen(drop_target_node->ie_IconListEntry.label) + 1, MEMF_CLEAR)) == NULL)
6400 bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__);
6401 goto dragdropdone;
6403 strcpy(dragDropEvent->drop_TargetPath, drop_target_node->ie_IconListEntry.label);
6406 #if defined(DEBUG_ILC_ICONDRAGDROP)
6407 D(bug("[IconList] %s: Target Entry Full Path = '%s'\n", __PRETTY_FUNCTION__, dragDropEvent->drop_TargetPath));
6408 #endif
6409 /* mark the Entry the selection was dropped on*/
6410 //drop_target_node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6411 //data->icld_UpdateMode = UPDATE_SINGLEENTRY;
6412 //data->update_entry = drop_target_node;
6413 //MUI_Redraw(obj,MADF_DRAWUPDATE);
6415 else
6417 /* not dropped on entry -> get path of DESTINATION iconlist */
6418 /* Note: directory_path is NULL when dropped on Wanderer's desktop */
6419 if ((message->obj != obj) && directory_path)
6421 #if defined(DEBUG_ILC_ICONDRAGDROP)
6422 D(bug("[IconList] %s: drop entry: Icons dropped in window '%s'\n", __PRETTY_FUNCTION__, directory_path));
6423 #endif
6424 /* copy path */
6425 if ((dragDropEvent->drop_TargetPath = AllocVec(strlen(directory_path) + 1, MEMF_CLEAR)) != NULL)
6427 strcpy(dragDropEvent->drop_TargetPath, directory_path);
6429 else
6431 #if defined(DEBUG_ILC_ICONDRAGDROP)
6432 D(bug("[IconList] %s: Failed to allocate IconList_Drop_Event->drop_TargetPath Storage!\n", __PRETTY_FUNCTION__));
6433 #endif
6434 goto dragdropdone;
6437 else if (message->obj == obj)
6439 #if defined(DEBUG_ILC_ICONDRAGDROP)
6440 D(bug("[IconList] %s: drop entry: Entry Move detected ..\n", __PRETTY_FUNCTION__));
6441 #endif
6442 iconMove = TRUE;
6443 SET(obj, MUIA_IconList_IconsMoved, (IPTR)entry); // Now notify
6444 MUI_Redraw(obj,MADF_DRAWOBJECT);
6445 DoMethod(obj, MUIM_IconList_CoordsSort);
6447 else
6449 #if defined(DEBUG_ILC_ICONDRAGDROP)
6450 D(bug("[IconList] %s: Icons Dropped on Wanderer Desktop (unhandled)!\n", __PRETTY_FUNCTION__));
6451 #endif
6452 iconMove = TRUE;
6455 if (!(iconMove))
6457 int copycount = 0;
6458 /* Create list of entries to copy .. */
6459 entry = (IPTR)MUIV_IconList_NextIcon_Start;
6460 while (entry != (IPTR)MUIV_IconList_NextIcon_End)
6462 DoMethod(message->obj, MUIM_IconList_NextIcon, MUIV_IconList_NextIcon_Selected, (IPTR)&entry);
6464 if (entry != (IPTR)MUIV_IconList_NextIcon_End)
6466 struct IconList_Drop_SourceEntry *sourceEntry = NULL;
6467 sourceEntry = AllocMem(sizeof(struct IconList_Drop_SourceEntry), MEMF_CLEAR);
6468 if ((entry->type != ST_ROOT) && (entry->type != ST_SOFTLINK))
6470 int fulllen = 0;
6471 char *path = NULL;
6473 GET(message->obj, MUIA_IconDrawerList_Drawer, &path);
6474 /* Properly expand the location incase it uses devices rather than volumes */
6475 if (path != NULL)
6477 tmp_dirlock = Lock(path, SHARED_LOCK);
6478 if (tmp_dirlock)
6480 if (NameFromLock(tmp_dirlock, tmp_dirbuff, 256))
6482 path = tmp_dirbuff;
6484 UnLock(tmp_dirlock);
6487 if (strcasecmp(dragDropEvent->drop_TargetPath, path) != 0)
6489 fulllen = strlen(path) + strlen(entry->ile_IconEntry->ie_IconNode.ln_Name) + 2;
6490 sourceEntry->dropse_Node.ln_Name = AllocVec(fulllen, MEMF_CLEAR);
6491 strcpy(sourceEntry->dropse_Node.ln_Name, path);
6492 AddPart(sourceEntry->dropse_Node.ln_Name, entry->label, fulllen);
6493 #if defined(DEBUG_ILC_ICONDRAGDROP)
6494 D(bug("[IconList] %s: Source Entry (Full Path) = '%s'\n", __PRETTY_FUNCTION__, sourceEntry->dropse_Node.ln_Name));
6495 #endif
6499 else
6501 sourceEntry->dropse_Node.ln_Name = AllocVec(strlen(entry->label) + 1, MEMF_CLEAR);
6502 strcpy(sourceEntry->dropse_Node.ln_Name, entry->label);
6503 #if defined(DEBUG_ILC_ICONDRAGDROP)
6504 D(bug("[IconList] %s: Source Entry = '%s'\n", __PRETTY_FUNCTION__, sourceEntry->dropse_Node.ln_Name));
6505 #endif
6508 if ((sourceEntry->dropse_Node.ln_Name != NULL) && (strcasecmp(dragDropEvent->drop_TargetPath, sourceEntry->dropse_Node.ln_Name) != 0))
6510 copycount += 1;
6511 AddTail(&dragDropEvent->drop_SourceList, &sourceEntry->dropse_Node);
6513 else
6515 #if defined(DEBUG_ILC_ICONDRAGDROP)
6516 D(bug("[IconList] %s: Source == Dest, Skipping!\n", __PRETTY_FUNCTION__));
6517 #endif
6518 if ( sourceEntry->dropse_Node.ln_Name) FreeVec(sourceEntry->dropse_Node.ln_Name);
6519 FreeMem(sourceEntry, sizeof(struct IconList_Drop_SourceEntry));
6523 if (copycount > 0)
6525 dragDropEvent->drop_TargetObj = (IPTR)obj;
6527 #if defined(DEBUG_ILC_ICONDRAGDROP)
6528 D(bug("[IconList] %s: Causing DROP notification..\n", __PRETTY_FUNCTION__));
6529 #endif
6530 SET(obj, MUIA_IconList_IconsDropped, (IPTR)dragDropEvent);
6531 DoMethod(obj, MUIM_IconList_CoordsSort);
6533 else
6535 if (dragDropEvent->drop_TargetPath) FreeVec(dragDropEvent->drop_TargetPath);
6536 FreeMem(dragDropEvent, sizeof(struct IconList_Drop_Event));
6540 else
6542 #if defined(DEBUG_ILC_ICONDRAGDROP)
6543 D(bug("[IconList] %s: BUG - DragDrop recieved with no source icons!\n", __PRETTY_FUNCTION__));
6544 #endif
6545 NNSET(obj, MUIA_IconList_IconsDropped, (IPTR)NULL);
6548 dragdropdone:
6549 return DoSuperMethodA(CLASS, obj, (Msg)message);
6553 ///MUIM_UnselectAll()
6554 /**************************************************************************
6555 MUIM_UnselectAll
6556 **************************************************************************/
6557 IPTR IconList__MUIM_IconList_UnselectAll(struct IClass *CLASS, Object *obj, Msg message)
6559 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6560 struct Node *node = NULL, *next_node = NULL;
6561 BOOL changed = FALSE;
6563 #if defined(DEBUG_ILC_FUNCS)
6564 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6565 #endif
6567 data->icld_SelectionLastClicked = NULL;
6568 data->icld_FocusIcon = NULL;
6569 #if defined(__AROS__)
6570 ForeachNodeSafe(&data->icld_SelectionList, node, next_node)
6571 #else
6572 Foreach_NodeSafe(&data->icld_SelectionList, node, next_node);
6573 #endif
6575 struct IconEntry *entry = (struct IconEntry *)((IPTR)node - ((IPTR)&entry->ie_SelectionNode - (IPTR)entry));
6576 BOOL update_entry = FALSE;
6578 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6580 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
6582 Remove(node);
6583 entry->ie_Flags &= ~ICONENTRY_FLAG_SELECTED;
6584 update_entry = TRUE;
6586 if (entry->ie_Flags & ICONENTRY_FLAG_FOCUS)
6588 entry->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
6589 update_entry = TRUE;
6593 if (update_entry)
6595 changed = TRUE;
6596 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
6597 data->update_entry = entry;
6598 MUI_Redraw(obj, MADF_DRAWUPDATE);
6602 if (changed)
6603 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
6605 return 1;
6609 ///MUIM_SelectAll()
6610 /**************************************************************************
6611 MUIM_SelectAll
6612 **************************************************************************/
6613 IPTR IconList__MUIM_IconList_SelectAll(struct IClass *CLASS, Object *obj, Msg message)
6615 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6616 struct IconEntry *node = NULL;
6617 BOOL changed = FALSE;
6619 #if defined(DEBUG_ILC_FUNCS)
6620 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6621 #endif
6623 node = (struct IconEntry *)GetHead(&data->icld_IconList);
6625 while (node != NULL)
6627 if (node->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6629 BOOL update_entry = FALSE;
6631 if (!(node->ie_Flags & ICONENTRY_FLAG_SELECTED))
6633 AddTail(&data->icld_SelectionList, &node->ie_SelectionNode);
6634 node->ie_Flags |= ICONENTRY_FLAG_SELECTED;
6635 update_entry = TRUE;
6637 data->icld_SelectionLastClicked = node;
6639 else if (node->ie_Flags & ICONENTRY_FLAG_FOCUS)
6641 node->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
6642 update_entry = TRUE;
6645 if (update_entry)
6647 changed = TRUE;
6648 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
6649 data->update_entry = node;
6650 MUI_Redraw(obj, MADF_DRAWUPDATE);
6653 node = (struct IconEntry *)GetSucc(&node->ie_IconNode);
6656 if ((data->icld_SelectionLastClicked) && (data->icld_SelectionLastClicked != data->icld_FocusIcon))
6658 data->icld_FocusIcon = data->icld_SelectionLastClicked;
6659 if (!(data->icld_FocusIcon->ie_Flags & ICONENTRY_FLAG_FOCUS))
6661 data->icld_FocusIcon->ie_Flags &= ~ICONENTRY_FLAG_FOCUS;
6662 data->icld_FocusIcon->ie_Flags |= ICONENTRY_FLAG_FOCUS;
6663 data->icld_UpdateMode = UPDATE_SINGLEENTRY;
6664 data->update_entry = data->icld_FocusIcon;
6665 MUI_Redraw(obj, MADF_DRAWUPDATE);
6669 if (changed)
6670 SET(obj, MUIA_IconList_SelectionChanged, TRUE);
6672 return 1;
6676 ///IconList__MUIM_IconList_CoordsSort()
6677 IPTR IconList__MUIM_IconList_CoordsSort(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Sort *message)
6679 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6681 struct IconEntry *entry = NULL,
6682 *test_icon = NULL;
6684 struct List list_VisibleIcons;
6685 struct List list_HiddenIcons;
6688 perform a quick sort of the iconlist based on entry coords
6689 this method DOESNT cause any visual output.
6691 #if defined(DEBUG_ILC_FUNCS) && defined(DEBUG_ILC_ICONSORTING)
6692 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6693 #endif
6695 NewList((struct List*)&list_VisibleIcons);
6696 NewList((struct List*)&list_HiddenIcons);
6698 /*move list into our local list struct(s)*/
6699 while ((entry = (struct IconEntry *)RemTail((struct List*)&data->icld_IconList)))
6701 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6702 AddHead((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
6703 else
6704 AddHead((struct List*)&list_HiddenIcons, (struct Node *)&entry->ie_IconNode);
6707 while ((entry = (struct IconEntry *)RemTail((struct List*)&list_VisibleIcons)))
6709 if ((test_icon = (struct IconEntry *)GetTail(&data->icld_IconList)) != NULL)
6711 while (test_icon != NULL)
6713 if (((data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconX > entry->ie_IconX)) ||
6714 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconY > entry->ie_IconY)))
6716 test_icon = (struct IconEntry *)GetPred(&test_icon->ie_IconNode);
6717 continue;
6719 else break;
6722 while (test_icon != NULL)
6724 if (((data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconY > entry->ie_IconY)) ||
6725 (!(data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL) && (test_icon->ie_IconX > entry->ie_IconX)))
6727 test_icon = (struct IconEntry *)GetPred(&test_icon->ie_IconNode);
6728 continue;
6730 else break;
6732 Insert((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode, (struct Node *)&test_icon->ie_IconNode);
6734 else
6735 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
6737 #if defined(DEBUG_ILC_ICONSORTING)
6738 D(bug("[IconList] %s: Done\n", __PRETTY_FUNCTION__));
6739 #endif
6741 while ((entry = (struct IconEntry *)RemTail((struct List*)&list_HiddenIcons)))
6743 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
6746 #if defined(DEBUG_ILC_ICONSORTING_DUMP)
6747 #if defined(__AROS__)
6748 ForeachNode(&data->icld_IconList, entry)
6749 #else
6750 Foreach_Node(&data->icld_IconList, entry);
6751 #endif
6753 D(bug("[IconList] %s: %d %d '%s'\n", __PRETTY_FUNCTION__, entry->ie_IconX, entry->ie_IconY, entry->ie_IconListEntry.label));
6755 #endif
6757 return TRUE;
6761 ///MUIM_Sort()
6762 /**************************************************************************
6763 MUIM_Sort - sortsort
6764 **************************************************************************/
6765 IPTR IconList__MUIM_IconList_Sort(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Sort *message)
6767 struct IconList_DATA *data = INST_DATA(CLASS, obj);
6768 struct IconEntry *entry = NULL,
6769 *icon1 = NULL,
6770 *icon2 = NULL;
6772 struct List list_VisibleIcons,
6773 list_SortedIcons,
6774 list_HiddenIcons;
6776 BOOL sortme, enqueue = FALSE;
6777 int i, visible_count = 0;
6779 #if defined(DEBUG_ILC_FUNCS) && defined(DEBUG_ILC_ICONSORTING)
6780 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
6781 #endif
6783 /* Reset incase view options have changed .. */
6784 data->icld_IconAreaLargestWidth = 0;
6785 data->icld_IconAreaLargestHeight = 0;
6786 data->icld_IconLargestHeight = 0;
6787 data->icld_LabelLargestHeight = 0;
6789 if ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) != 0)
6791 #if defined(DEBUG_ILC_ICONSORTING)
6792 D(bug("[IconList] %s: Sorting (Flags %x)\n", __PRETTY_FUNCTION__, (data->icld_SortFlags & MUIV_IconList_Sort_MASK)));
6793 #endif
6794 NewList((struct List*)&list_VisibleIcons);
6795 NewList((struct List*)&list_SortedIcons);
6796 NewList((struct List*)&list_HiddenIcons);
6798 /*move list into our local list struct(s)*/
6799 while ((entry = (struct IconEntry *)RemTail((struct List*)&data->icld_IconList)))
6801 if (entry->ie_DiskObj)
6803 if (entry->ie_IconX != entry->ie_DiskObj->do_CurrentX)
6805 entry->ie_IconX = entry->ie_DiskObj->do_CurrentX;
6806 if ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == 0)
6807 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
6809 if (entry->ie_IconY != entry->ie_DiskObj->do_CurrentY)
6811 entry->ie_IconY = entry->ie_DiskObj->do_CurrentY;
6812 if ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == 0)
6813 entry->ie_Flags |= ICONENTRY_FLAG_NEEDSUPDATE;
6817 if (!(entry->ie_Flags & ICONENTRY_FLAG_HASICON))
6819 if (data->icld_DisplayFlags & ICONLIST_DISP_SHOWINFO)
6821 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6823 entry->ie_Flags &= ~(ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
6826 else if (!(entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
6828 entry->ie_Flags |= (ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
6831 else
6833 if (!(entry->ie_Flags & ICONENTRY_FLAG_VISIBLE))
6835 entry->ie_Flags |= (ICONENTRY_FLAG_VISIBLE|ICONENTRY_FLAG_NEEDSUPDATE);
6839 /* Now we have fixed visibility lets dump them into the correct list for sorting */
6840 if (entry->ie_Flags & ICONENTRY_FLAG_VISIBLE)
6842 if(entry->ie_AreaWidth > data->icld_IconAreaLargestWidth) data->icld_IconAreaLargestWidth = entry->ie_AreaWidth;
6843 if(entry->ie_AreaHeight > data->icld_IconAreaLargestHeight) data->icld_IconAreaLargestHeight = entry->ie_AreaHeight;
6844 if(entry->ie_IconHeight > data->icld_IconLargestHeight) data->icld_IconLargestHeight = entry->ie_IconHeight;
6845 if((entry->ie_AreaHeight - entry->ie_IconHeight) > data->icld_LabelLargestHeight) data->icld_LabelLargestHeight = entry->ie_AreaHeight - entry->ie_IconHeight;
6847 if (((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == 0) && (entry->ie_IconX == NO_ICON_POSITION))
6848 AddTail((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
6849 else
6850 AddHead((struct List*)&list_VisibleIcons, (struct Node *)&entry->ie_IconNode);
6851 visible_count++;
6853 else
6855 if (entry->ie_Flags & ICONENTRY_FLAG_SELECTED)
6857 Remove(&entry->ie_SelectionNode);
6859 entry->ie_Flags &= ~(ICONENTRY_FLAG_SELECTED|ICONENTRY_FLAG_FOCUS);
6860 if (data->icld_SelectionLastClicked == entry) data->icld_SelectionLastClicked = NULL;
6861 if (data->icld_FocusIcon == entry) data->icld_FocusIcon = data->icld_SelectionLastClicked;
6862 AddHead((struct List*)&list_HiddenIcons, (struct Node *)&entry->ie_IconNode);
6866 /* Copy each visible entry back to the main list, sorting as we go*/
6868 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_VisibleIcons)))
6870 icon1 = (struct IconEntry *)GetHead(&list_SortedIcons);
6871 icon2 = NULL;
6873 sortme = FALSE;
6875 if (visible_count > 1)
6877 // D(bug(" - %s %s %s %i\n",entry->ie_IconListEntry.label,entry->ie_TxtBuf_DATE,entry->ie_TxtBuf_TIME,entry->ie_FileInfoBlock->fib_Size));
6879 while (icon1)
6881 if(((icon1->ie_IconListEntry.type == ST_ROOT) || (icon1->ie_IconListEntry.type == ST_LINKDIR) || (icon1->ie_IconListEntry.type == ST_LINKFILE))
6882 || (data->icld_SortFlags & MUIV_IconList_Sort_DrawersMixed))
6884 /*volume list or drawers mixed*/
6885 sortme = TRUE;
6887 else
6889 /*drawers first*/
6890 if ((icon1->ie_IconListEntry.type == ST_USERDIR) && (entry->ie_IconListEntry.type == ST_USERDIR))
6892 sortme = TRUE;
6894 else
6896 if ((icon1->ie_IconListEntry.type != ST_USERDIR) && (entry->ie_IconListEntry.type != ST_USERDIR))
6897 sortme = TRUE;
6898 else
6900 /* we are the first drawer to arrive or we need to insert ourselves
6901 due to being sorted to the end of the drawers*/
6903 if ((!icon2 || icon2->ie_IconListEntry.type == ST_USERDIR) &&
6904 (entry->ie_IconListEntry.type == ST_USERDIR) &&
6905 (icon1->ie_IconListEntry.type != ST_USERDIR))
6907 // D(bug("force %s\n",entry->ie_IconListEntry.label));
6908 break;
6914 if (sortme)
6916 i = 0;
6918 if ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == MUIV_IconList_Sort_ByDate)
6920 /* Sort by Date */
6921 i = CompareDates((const struct DateStamp *)&entry->ie_FileInfoBlock->fib_Date,(const struct DateStamp *)&icon1->ie_FileInfoBlock->fib_Date);
6923 else if ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == MUIV_IconList_Sort_BySize)
6925 /* Sort by Size .. */
6926 i = entry->ie_FileInfoBlock->fib_Size - icon1->ie_FileInfoBlock->fib_Size;
6928 else if (((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == MUIV_IconList_Sort_MASK) && ((entry->ie_IconListEntry.type == ST_FILE) || (entry->ie_IconListEntry.type == ST_USERDIR)))
6930 /* Sort by Type .. */
6931 #warning "TODO: Sort icons based on type using datatypes"
6933 else
6935 if (
6936 ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == MUIV_IconList_Sort_MASK) ||
6937 ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == MUIV_IconList_Sort_ByName) ||
6938 (entry->ie_IconX == NO_ICON_POSITION)
6941 /* Sort by Name .. */
6942 i = Stricmp(entry->ie_IconListEntry.label, icon1->ie_IconListEntry.label);
6943 if ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) == MUIV_IconList_Sort_MASK)
6944 enqueue = TRUE;
6946 else
6948 /* coord sort */
6949 #warning "TODO: Implement default coord sorting.."
6953 if (data->icld_SortFlags & MUIV_IconList_Sort_Reverse)
6955 if (i > 0)
6956 break;
6958 else if (i < 0)
6959 break;
6961 icon2 = icon1;
6962 icon1 = (struct IconEntry *)GetSucc(&icon1->ie_IconNode);
6965 Insert((struct List*)&list_SortedIcons, (struct Node *)&entry->ie_IconNode, (struct Node *)&icon2->ie_IconNode);
6967 if (enqueue)
6969 /* Quickly resort based on node priorities .. */
6970 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_SortedIcons)))
6972 Enqueue((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
6975 else
6977 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_SortedIcons)))
6979 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
6983 else
6985 #if defined(DEBUG_ILC_ICONSORTING)
6986 D(bug("[IconList] %s: Coord Sorting\n", __PRETTY_FUNCTION__));
6987 #endif
6988 DoMethod(obj, MUIM_IconList_CoordsSort);
6991 DoMethod(obj, MUIM_IconList_PositionIcons);
6992 MUI_Redraw(obj, MADF_DRAWOBJECT);
6994 if ((data->icld_SortFlags & MUIV_IconList_Sort_MASK) != 0)
6996 DoMethod(obj, MUIM_IconList_CoordsSort);
6998 /* leave hidden icons on a seperate list to speed up normal list parsing ? */
6999 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_HiddenIcons)))
7001 AddTail((struct List*)&data->icld_IconList, (struct Node *)&entry->ie_IconNode);
7004 SET(obj, MUIA_IconList_Changed, TRUE);
7006 return 1;
7010 ///MUIM_DragReport()
7011 /**************************************************************************
7012 MUIM_DragReport. Since MUI doesn't change the drop object if the dragged
7013 object is moved above another window (while still in the bounds of the
7014 orginal drop object) we must do it here manually to be compatible with
7015 MUI. Maybe Zune should fix this bug somewhen.
7016 **************************************************************************/
7017 IPTR IconList__MUIM_DragReport(struct IClass *CLASS, Object *obj, struct MUIP_DragReport *message)
7019 struct Window *wnd = _window(obj);
7020 struct Layer *l = NULL;
7022 #if defined(DEBUG_ILC_FUNCS)
7023 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7024 #endif
7026 l = WhichLayer(&wnd->WScreen->LayerInfo, wnd->LeftEdge + message->x, wnd->TopEdge + message->y);
7028 if (l != wnd->WLayer) return MUIV_DragReport_Abort;
7030 return MUIV_DragReport_Continue;
7034 ///MUIM_IconList_UnknownDropDestination()
7035 /**************************************************************************
7036 MUIM_IconList_UnknownDropDestination
7037 **************************************************************************/
7038 IPTR IconList__MUIM_UnknownDropDestination(struct IClass *CLASS, Object *obj, struct MUIP_UnknownDropDestination *message)
7040 #if defined(DEBUG_ILC_FUNCS)
7041 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7042 #endif
7043 D(bug("[IconList] %s: icons dropped on custom window \n", __PRETTY_FUNCTION__));
7045 SET(obj, MUIA_IconList_AppWindowDrop, (IPTR)message); /* Now notify */
7047 return (IPTR)NULL;
7051 ///MUIM_IconList_MakeEntryVisible()
7052 /**************************************************************************
7053 Move the visible area so that the selected entry becomes visible ..
7054 **************************************************************************/
7055 IPTR IconList__MUIM_IconList_MakeEntryVisible(struct IClass *CLASS, Object *obj, struct MUIP_IconList_MakeEntryVisible *message)
7057 struct IconList_DATA *data = INST_DATA(CLASS, obj);
7058 BOOL viewmoved = FALSE;
7059 struct Rectangle iconrect, viewrect;
7061 #if defined(DEBUG_ILC_FUNCS)
7062 D(bug("[IconList]: %s()\n", __PRETTY_FUNCTION__));
7063 #endif
7065 viewrect.MinX = data->icld_ViewX;
7066 viewrect.MaxX = data->icld_ViewX + data->icld_AreaWidth;
7067 viewrect.MinY = data->icld_ViewY;
7068 viewrect.MaxY = data->icld_ViewY + data->icld_AreaHeight;
7070 IconList_GetIconAreaRectangle(obj, data, message->entry, &iconrect);
7072 if (!(RectAndRect(&viewrect, &iconrect)))
7074 viewmoved = TRUE;
7075 if (message->entry->ie_IconX < data->icld_ViewX)
7076 data->icld_ViewX = message->entry->ie_IconX;
7077 else if (message->entry->ie_IconX > (data->icld_ViewX + data->icld_AreaWidth))
7078 data->icld_ViewX = (message->entry->ie_IconX + message->entry->ie_AreaWidth) - data->icld_AreaWidth;
7080 if (message->entry->ie_IconY < data->icld_ViewY)
7081 data->icld_ViewY = message->entry->ie_IconX;
7082 else if (message->entry->ie_IconY > (data->icld_ViewY + data->icld_AreaHeight))
7083 data->icld_ViewY = (message->entry->ie_IconY + message->entry->ie_AreaHeight) - data->icld_AreaHeight;
7086 if (viewmoved)
7088 D(bug("[IconList]: %s: call SetSuperAttrs()\n", __PRETTY_FUNCTION__));
7089 SetSuperAttrs(CLASS, obj, MUIA_Virtgroup_Left, data->icld_ViewX,
7090 MUIA_Virtgroup_Top, data->icld_ViewY,
7091 TAG_DONE);
7093 D(bug("[IconList]: %s: call SetAttrs()\n", __PRETTY_FUNCTION__));
7094 SetAttrs(obj, MUIA_Virtgroup_Left, data->icld_ViewX,
7095 MUIA_Virtgroup_Top, data->icld_ViewY,
7096 TAG_DONE);
7098 D(bug("[IconList]: %s: call MUI_Redraw()\n", __PRETTY_FUNCTION__));
7099 MUI_Redraw(obj,MADF_DRAWOBJECT);
7101 return 1;
7104 #if defined(WANDERER_BUILTIN_ICONLIST)
7105 BOOPSI_DISPATCHER(IPTR,IconList_Dispatcher, CLASS, obj, message)
7107 #if defined(__AROS__)
7108 switch (message->MethodID)
7109 #else
7110 struct IClass *CLASS = cl;
7111 Msg message = msg;
7113 switch (msg->MethodID)
7114 #endif
7116 case OM_NEW: return IconList__OM_NEW(CLASS, obj, (struct opSet *)message);
7117 case OM_DISPOSE: return IconList__OM_DISPOSE(CLASS, obj, message);
7118 case OM_SET: return IconList__OM_SET(CLASS, obj, (struct opSet *)message);
7119 case OM_GET: return IconList__OM_GET(CLASS, obj, (struct opGet *)message);
7120 case OM_ADDMEMBER:
7121 case MUIM_Family_AddTail: return IconList__MUIM_Family_AddTail(CLASS, obj, (APTR)message);
7122 case MUIM_Family_AddHead: return IconList__MUIM_Family_AddHead(CLASS, obj, (APTR)message);
7123 case OM_REMMEMBER:
7124 case MUIM_Family_Remove: return IconList__MUIM_Family_Remove(CLASS, obj, (APTR)message);
7126 case MUIM_Setup: return IconList__MUIM_Setup(CLASS, obj, (struct MUIP_Setup *)message);
7128 case MUIM_Show: return IconList__MUIM_Show(CLASS,obj, (struct MUIP_Show *)message);
7129 case MUIM_Hide: return IconList__MUIM_Hide(CLASS,obj, (struct MUIP_Hide *)message);
7130 case MUIM_Cleanup: return IconList__MUIM_Cleanup(CLASS, obj, (struct MUIP_Cleanup *)message);
7131 case MUIM_AskMinMax: return IconList__MUIM_AskMinMax(CLASS, obj, (struct MUIP_AskMinMax *)message);
7132 case MUIM_Draw: return IconList__MUIM_Draw(CLASS, obj, (struct MUIP_Draw *)message);
7133 #if defined(__AROS__)
7134 case MUIM_Layout: return IconList__MUIM_Layout(CLASS, obj, (struct MUIP_Layout *)message);
7135 #endif
7136 case MUIM_HandleEvent: return IconList__MUIM_HandleEvent(CLASS, obj, (struct MUIP_HandleEvent *)message);
7137 case MUIM_CreateDragImage: return IconList__MUIM_CreateDragImage(CLASS, obj, (APTR)message);
7138 case MUIM_DeleteDragImage: return IconList__MUIM_DeleteDragImage(CLASS, obj, (APTR)message);
7139 case MUIM_DragQuery: return IconList__MUIM_DragQuery(CLASS, obj, (APTR)message);
7140 case MUIM_DragReport: return IconList__MUIM_DragReport(CLASS, obj, (APTR)message);
7141 case MUIM_DragDrop: return IconList__MUIM_DragDrop(CLASS, obj, (APTR)message);
7142 #if defined(__AROS__)
7143 case MUIM_UnknownDropDestination: return IconList__MUIM_UnknownDropDestination(CLASS, obj, (APTR)message);
7144 #endif
7145 case MUIM_IconList_Update: return IconList__MUIM_IconList_Update(CLASS, obj, (APTR)message);
7146 case MUIM_IconList_Clear: return IconList__MUIM_IconList_Clear(CLASS, obj, (APTR)message);
7147 case MUIM_IconList_RethinkDimensions: return IconList__MUIM_IconList_RethinkDimensions(CLASS, obj, (APTR)message);
7148 case MUIM_IconList_CreateEntry: return IconList__MUIM_IconList_CreateEntry(CLASS, obj, (APTR)message);
7149 case MUIM_IconList_UpdateEntry: return IconList__MUIM_IconList_UpdateEntry(CLASS, obj, (APTR)message);
7150 case MUIM_IconList_DestroyEntry: return IconList__MUIM_IconList_DestroyEntry(CLASS, obj, (APTR)message);
7151 case MUIM_IconList_DrawEntry: return IconList__MUIM_IconList_DrawEntry(CLASS, obj, (APTR)message);
7152 case MUIM_IconList_DrawEntryLabel: return IconList__MUIM_IconList_DrawEntryLabel(CLASS, obj, (APTR)message);
7153 case MUIM_IconList_NextIcon: return IconList__MUIM_IconList_NextIcon(CLASS, obj, (APTR)message);
7154 case MUIM_IconList_GetIconPrivate: return IconList__MUIM_IconList_GetIconPrivate(CLASS, obj, (APTR)message);
7155 case MUIM_IconList_UnselectAll: return IconList__MUIM_IconList_UnselectAll(CLASS, obj, (APTR)message);
7156 case MUIM_IconList_Sort: return IconList__MUIM_IconList_Sort(CLASS, obj, (APTR)message);
7157 case MUIM_IconList_CoordsSort: return IconList__MUIM_IconList_CoordsSort(CLASS, obj, (APTR)message);
7158 case MUIM_IconList_PositionIcons: return IconList__MUIM_IconList_PositionIcons(CLASS, obj, (APTR)message);
7159 case MUIM_IconList_SelectAll: return IconList__MUIM_IconList_SelectAll(CLASS, obj, (APTR)message);
7160 case MUIM_IconList_MakeEntryVisible: return IconList__MUIM_IconList_MakeEntryVisible(CLASS, obj, (APTR)message);
7163 return DoSuperMethodA(CLASS, obj, message);
7165 BOOPSI_DISPATCHER_END
7167 #if defined(__AROS__)
7168 /* Class descriptor. */
7169 const struct __MUIBuiltinClass _MUI_IconList_desc = {
7170 MUIC_IconList,
7171 MUIC_Area,
7172 sizeof(struct IconList_DATA),
7173 (void*)IconList_Dispatcher
7175 #endif
7176 #endif /* WANDERER_BUILTIN_ICONLIST */
7178 #if !defined(__AROS__)
7179 struct MUI_CustomClass *initIconListClass(void)
7181 return (struct MUI_CustomClass *) MUI_CreateCustomClass(NULL, MUIC_Area, NULL, sizeof(struct IconList_DATA), ENTRY(IconList_Dispatcher));
7183 #endif