Some fix for scrolling with lasso.
[tangerine.git] / workbench / libs / muimaster / classes / iconlist.c
blob5fc9644c81f1f05710c439d0db3d6973e8c5bf15
2 /*
3 Copyright 2002-2006, The AROS Development Team. All rights reserved.
4 $Id$
5 */
7 //#define MYDEBUG
8 #include "debug.h"
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <math.h>
16 #include <dos/dos.h>
17 #include <dos/datetime.h>
19 #include <exec/memory.h>
20 #include <graphics/gfx.h>
21 #include <graphics/view.h>
22 #include <graphics/rpattr.h>
23 #include <workbench/icon.h>
24 #include <workbench/workbench.h>
25 #include <devices/rawkeycodes.h>
26 #include <clib/alib_protos.h>
27 #include <proto/exec.h>
28 #include <proto/graphics.h>
29 #include <proto/utility.h>
30 #include <proto/dos.h>
31 #include <proto/intuition.h>
32 #include <proto/icon.h>
33 #include <proto/layers.h>
34 #include <proto/muimaster.h>
35 #include <proto/dos.h>
36 #include <proto/iffparse.h>
37 #include <prefs/prefhdr.h>
38 #include <prefs/wanderer.h>
39 #include <proto/cybergraphics.h>
41 #include "mui.h"
42 #include "muimaster_intern.h"
43 #include "support.h"
44 #include "imspec.h"
45 #include "iconlist.h"
47 extern struct Library *MUIMasterBase;
49 #ifndef NO_ICON_POSITION
50 #define NO_ICON_POSITION (0x8000000) /* belongs to workbench/workbench.h */
51 #endif
53 #ifdef __AROS__
54 #define dol_Name dol_OldName /* This doesn't work really */
55 #endif
57 #define UPDATE_SINGLEICON 1
58 #define UPDATE_SCROLL 2
59 #define UPDATE_SORT 3
60 #define UPDATE_RESCALE 4
62 #define LEFT_BUTTON 1
63 #define RIGHT_BUTTON 2
64 #define MIDDLE_BUTTON 4
66 #define ICONLIST_TEXTMARGIN 5
68 #define ICON_LISTMODE_GRID 0
69 #define ICON_LISTMODE_ROUGH 1
71 #define ICON_TEXTMODE_OUTLINE 0
72 #define ICON_TEXTMODE_PLAIN 1
73 #define ICON_TEXTMODE_DROPSHADOW 2
75 #define ICON_TEXTMAXLEN_DEFAULT 15
76 #define ICONLIST_DRAWMODE_NORMAL 1
77 #define ICONLIST_DRAWMODE_FAST 2
79 struct MUI_IconData
81 IPTR icld_Pool; /* Pool to allocate data from */
83 struct RastPort *icld_BufferRastPort;
84 struct TextFont *icld_IconFont;
86 struct List icld_IconList; /* IconEntry */
88 LONG icld_ViewX, /* the leftmost/upper coordinates of the view */
89 icld_ViewY;
90 ULONG icld_ViewWidth, /* dimensions of the view (_mwidth(obj) and _mheight(obj)) */
91 icld_ViewHeight,
92 width, /* The whole width/height */
93 height;
96 /* Selection & Drag/Drop Info .. */
97 struct IconEntry *icld_SelectionFirst; /* the icon which has been selected first or NULL */
98 struct IconEntry *icld_SelectionLast;
100 struct IconList_Drop drop_entry; /* the icon where the icons have been dropped */
101 struct IconList_Click icon_click;
103 /* Input / Event Information */
104 struct MUI_EventHandlerNode ehn;
106 LONG touch_x;
107 LONG touch_y;
109 LONG click_x;
110 LONG click_y;
112 ULONG last_secs; /* DoubleClick stuff */
113 ULONG last_mics;
115 /* RENDERING DATA! ###### */
116 ULONG icld_DisplayFlags; /* Internal Sorting related stuff */
117 ULONG icld_SortFlags;
118 ULONG icld_IconLargestWidth;
119 ULONG icld_IconLargestHeight;
121 /* values for icld_UpdateMode - :
123 UPDATE_SINGLEICON = draw the given single icon only
124 UPDATE_SCROLL = scroll the view by update_scrolldx/update_scrolldy
125 UPDATE_RESCALE = rescaling window */
127 ULONG icld_UpdateMode;
128 WORD update_scrolldx;
129 WORD update_scrolldy;
130 WORD update_oldwidth;
131 WORD update_oldheight;
133 struct IconEntry *update_icon;
134 struct Rectangle *update_rect1;
135 struct Rectangle *update_rect2;
136 struct Rectangle view_rect;
138 ULONG textWidth; /* Whole textwidth for icon in pixels */
140 struct Rectangle icld_LassoRectangle; /* lasso data */
141 BOOL icld_LassoActive;
143 /* IconList configuration settings ... */
144 ULONG icld_LabelPen;
145 ULONG icld_LabelShadowPen;
146 ULONG icld_InfoPen;
147 ULONG icld_InfoShadowPen;
149 ULONG icld__Option_IconTextMaxLen;
150 UBYTE icld__Option_IconListMode;
151 UBYTE icld__Option_IconTextMode;
152 BOOL icld__Option_IconListFixedBackground;
153 BOOL icld__Option_IconListScaledBackground;
155 UBYTE mouse_pressed;
158 /**************************************************************************
160 **************************************************************************/
161 int RectAndRect(struct Rectangle *a, struct Rectangle *b)
163 if ((a->MinX > b->MaxX) || (a->MinY > b->MaxY) || (a->MaxX < b->MinX) || (a->MaxY < b->MinY))
164 return 0;
165 return 1;
168 /**************************************************************************
169 get positive lasso coords
170 **************************************************************************/
171 static void GetAbsoluteLassoRect(struct MUI_IconData *data, struct Rectangle *LassoRectangle)
173 WORD minx = data->icld_LassoRectangle.MinX;
174 WORD miny = data->icld_LassoRectangle.MinY;
175 WORD maxx = data->icld_LassoRectangle.MaxX;
176 WORD maxy = data->icld_LassoRectangle.MaxY;
178 D(bug("[IconList] GetAbsoluteLassoRect()\n"));
180 if (minx > maxx)
182 /* Swap minx, maxx */
183 minx ^= maxx;
184 maxx ^= minx;
185 minx ^= maxx;
188 if (miny > maxy)
190 /* Swap miny, maxy */
191 miny ^= maxy;
192 maxy ^= miny;
193 miny ^= maxy;
196 LassoRectangle->MinX = data->view_rect.MinX - data->icld_ViewX + minx;
197 LassoRectangle->MinY = data->view_rect.MinY - data->icld_ViewY + miny;
198 LassoRectangle->MaxX = data->view_rect.MinX - data->icld_ViewX + maxx;
199 LassoRectangle->MaxY = data->view_rect.MinY - data->icld_ViewY + maxy;
202 static void IconList_InvertPixelRect(struct RastPort *rp, WORD minx, WORD miny, WORD maxx, WORD maxy)
204 D(bug("[IconList] IconList_InvertPixelRect()\n"));
206 if (maxx < minx)
208 /* Swap minx, maxx */
209 minx ^= maxx;
210 maxx ^= minx;
211 minx ^= maxx;
214 if (maxy < miny)
216 /* Swap miny, maxy */
217 miny ^= maxy;
218 maxy ^= miny;
219 miny ^= maxy;
222 InvertPixelArray(rp, minx, miny, maxx - minx + 1, maxy - miny + 1);
225 /**************************************************************************
226 Simple lasso drawing by inverting area outlines
227 **************************************************************************/
228 void IconList_InvertLassoOutlines(Object *obj, struct Rectangle *rect)
230 struct Rectangle lasso;
232 D(bug("[IconList] IconList_InvertLassoOutlines()\n"));
234 /* get abolute iconlist coords */
235 lasso.MinX = rect->MinX + _mleft(obj);
236 lasso.MaxX = rect->MaxX + _mleft(obj);
237 lasso.MinY = rect->MinY + _mtop(obj);
238 lasso.MaxY = rect->MaxY + _mtop(obj);
240 /* check for vertical borders */
241 if ( lasso.MinX < _mleft(obj) ) lasso.MinX += _mleft(obj) - lasso.MinX;
242 if ( lasso.MaxX > _mright(obj) ) lasso.MaxX -= lasso.MaxX - _mright(obj) - 2;
244 /* horizontal lasso lines */
245 if ( lasso.MinY > _mtop(obj) ) IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MinY, lasso.MaxX-1, lasso.MinY + 1);
246 else lasso.MinY += _mtop(obj) - lasso.MinY;
247 if ( lasso.MaxY < _mbottom(obj) ) IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MaxY, lasso.MaxX-1, lasso.MaxY + 1);
248 else lasso.MaxY -= lasso.MaxY - _mbottom(obj) - 2;
250 /* vertical lasso lines */
251 if ( lasso.MinX > _mleft(obj) ) IconList_InvertPixelRect(_rp(obj), lasso.MinX, lasso.MinY, lasso.MinX + 1, lasso.MaxY - 1);
252 if ( lasso.MaxX < _mright(obj) ) IconList_InvertPixelRect(_rp(obj), lasso.MaxX, lasso.MinY, lasso.MaxX + 1, lasso.MaxY - 1);
255 /**************************************************************************
256 As we don't use the label drawing of icon.library we also have to do
257 this by hand
258 **************************************************************************/
259 static void IconList_GetIconRectangle(Object *obj, struct MUI_IconData *data, struct IconEntry *icon, struct Rectangle *rect)
261 D(bug("[IconList] IconList_GetIconRectangle()\n"));
262 /* Get basic width/height */
263 GetIconRectangleA(NULL, icon->ile_DiskObj, NULL, rect, NULL);
265 icon->ile_AreaWidth = (rect->MaxX - rect->MinX) + 1;
266 icon->ile_AreaHeight = (rect->MaxY - rect->MinY) + 1;
268 /* Get icon box width including text width */
269 if (icon->ile_IconListEntry.label)
271 SetFont(data->icld_BufferRastPort, data->icld_IconFont);
273 ULONG textlength = strlen(icon->ile_IconListEntry.label);
274 if ( !data->icld__Option_IconTextMaxLen ) data->icld__Option_IconTextMaxLen = ICON_TEXTMAXLEN_DEFAULT;
275 if ( textlength > data->icld__Option_IconTextMaxLen ) textlength = data->icld__Option_IconTextMaxLen;
277 LONG txwidth = TextLength(data->icld_BufferRastPort, icon->ile_IconListEntry.label, textlength) + 3;
279 if ( txwidth > icon->ile_AreaWidth ) icon->ile_AreaWidth = txwidth;
281 icon->ile_AreaHeight += data->icld_IconFont->tf_YSize + ICONLIST_TEXTMARGIN;
284 /* Date/size sorting has the date/size appended under the icon label
285 only list regular files like this (drawers have no size/date output) */
287 icon->ile_IconListEntry.type != WBDRAWER &&
288 ((data->icld_SortFlags & ICONLIST_SORT_BY_SIZE) || (data->icld_SortFlags & ICONLIST_SORT_BY_DATE))
291 icon->ile_AreaHeight += data->icld_IconFont->tf_YSize + ( ICONLIST_TEXTMARGIN * 2 );
294 /* Store */
295 icon->ile_IconWidth = rect->MaxX - rect->MinX + 1;
296 icon->ile_IconHeight = rect->MaxY - rect->MinY + 1;
297 rect->MaxX = rect->MinX + icon->ile_AreaWidth - 1;
298 rect->MaxY = rect->MinY + icon->ile_AreaHeight - 1;
301 /**************************************************************************
302 Draw the icon at its position
303 **************************************************************************/
305 #define DRAWICON_TESTDRAW TRUE
306 #define DRAWICON_DODRAW FALSE
308 static BOOL IconList_DrawIcon(Object *obj, struct MUI_IconData *data, struct IconEntry *icon, BOOL onlytest)
310 struct Rectangle iconrect;
311 struct Rectangle objrect;
313 LONG tx,ty,offsetx,offsety;
314 LONG txwidth; // txheight;
316 STRPTR buf = NULL;
318 D(bug("[IconList] IconList_DrawIcon(icon @ %x)\n", icon));
320 if ((!(icon->ile_Flags & ICONENTRY_FLAG_VISIBLE)) ||
321 (!(icon->ile_DiskObj)))
322 return FALSE;
324 /* Get the dimensions and affected area of icon */
325 IconList_GetIconRectangle(obj, data, icon, &iconrect);
327 /* Add the relative position offset of the icon */
328 offsetx = _mleft(obj) - data->icld_ViewX + icon->ile_IconX;
329 offsety = _mtop(obj) - data->icld_ViewY + icon->ile_IconY;
331 iconrect.MinX += offsetx;
332 iconrect.MinY += offsety;
333 iconrect.MaxX += offsetx;
334 iconrect.MaxY += offsety;
336 /* Add the relative position of the window */
337 objrect.MinX = _mleft(obj);
338 objrect.MinY = _mtop(obj);
339 objrect.MaxX = _mright(obj);
340 objrect.MaxY = _mbottom(obj);
342 if (!RectAndRect(&iconrect, &objrect)) return FALSE;
344 /* data->update_rect1 and data->update_rect2 may
345 point to rectangles to indicate that only icons
346 in any of this rectangles need to be drawn */
348 if (data->update_rect1 && data->update_rect2)
350 if (!RectAndRect(&iconrect, data->update_rect1) &&
351 !RectAndRect(&iconrect, data->update_rect2)) return FALSE;
353 else if (data->update_rect1)
355 if (!RectAndRect(&iconrect, data->update_rect1)) return FALSE;
357 else if (data->update_rect2)
359 if (!RectAndRect(&iconrect, data->update_rect2)) return FALSE;
362 if (onlytest) return TRUE;
364 if (data->icld_BufferRastPort == NULL)
366 data->icld_BufferRastPort = _rp(obj);
368 // else
369 // {
370 // iconrect.MinX -= offsetx;
371 // iconrect.MinY -= offsety;
372 // iconrect.MaxX -= offsetx;
373 // iconrect.MaxY -= offsety;
374 // }
376 SetABPenDrMd(data->icld_BufferRastPort, _pens(obj)[MPEN_TEXT], 0, JAM1);
378 // Center icon
379 ULONG iconX = iconrect.MinX + ((icon->ile_AreaWidth - icon->ile_IconWidth )/2);
380 ULONG iconY = iconrect.MinY;
382 #ifndef __AROS__
383 DrawIconState
385 data->icld_BufferRastPort ? data->icld_BufferRastPort : data->icld_BufferRastPort, icon->ile_DiskObj, NULL,
386 iconX, iconY,
387 ((icon->ile_Flags & ICONENTRY_FLAG_SELECTED)||(icon->ile_Flags & ICONENTRY_FLAG_FOCUS)) ? IDS_SELECTED : IDS_NORMAL,
388 ICONDRAWA_EraseBackground, FALSE,
389 TAG_DONE
391 #else
392 DrawIconStateA
394 data->icld_BufferRastPort ? data->icld_BufferRastPort : data->icld_BufferRastPort, icon->ile_DiskObj, NULL,
395 iconX,
396 iconY,
397 ((icon->ile_Flags & ICONENTRY_FLAG_SELECTED)||(icon->ile_Flags & ICONENTRY_FLAG_FOCUS)) ? IDS_SELECTED : IDS_NORMAL,
398 TAG_DONE
400 #endif
402 if (icon->ile_IconListEntry.label) buf = AllocVec ( 255, MEMF_CLEAR );
404 if (icon->ile_IconListEntry.label && buf)
406 ULONG nameLength = strlen(icon->ile_IconListEntry.label);
408 SetFont(data->icld_BufferRastPort, data->icld_IconFont);
410 if ( nameLength > data->icld__Option_IconTextMaxLen )
411 txwidth = TextLength(data->icld_BufferRastPort, icon->ile_IconListEntry.label, data->icld__Option_IconTextMaxLen);
412 else
413 txwidth = TextLength(data->icld_BufferRastPort, icon->ile_IconListEntry.label, nameLength);
415 ULONG len = data->icld__Option_IconTextMaxLen;
416 // Make sure the maxlen is at least the length of ".."
417 if ( len < 3 ) len = 3;
419 if(nameLength > len)
421 strncpy(buf, icon->ile_IconListEntry.label, len - 3);
422 strcat(buf , " ..");
423 nameLength = len;
425 else
427 strncpy( buf, icon->ile_IconListEntry.label, nameLength );
430 tx = iconrect.MinX + ((iconrect.MaxX - iconrect.MinX + 1 - txwidth)/2);
431 ty = iconY + icon->ile_IconHeight + data->icld_IconFont->tf_Baseline;
433 switch ( data->icld__Option_IconTextMode )
435 case ICON_TEXTMODE_DROPSHADOW:
436 case ICON_TEXTMODE_PLAIN:
437 SetAPen(data->icld_BufferRastPort, data->icld_LabelShadowPen);
438 Move(data->icld_BufferRastPort, tx, ty);
439 Text(data->icld_BufferRastPort, buf, nameLength);
440 break;
442 default:
443 // Outline mode:
445 SetSoftStyle(data->icld_BufferRastPort, FSF_BOLD, AskSoftStyle(data->icld_BufferRastPort));
446 SetAPen(data->icld_BufferRastPort, data->icld_LabelShadowPen);
448 Move(data->icld_BufferRastPort, tx + 1, ty ); Text(data->icld_BufferRastPort, buf, nameLength);
449 Move(data->icld_BufferRastPort, tx - 1, ty ); Text(data->icld_BufferRastPort, buf, nameLength);
450 Move(data->icld_BufferRastPort, tx, ty + 1); Text(data->icld_BufferRastPort, buf, nameLength);
451 Move(data->icld_BufferRastPort, tx, ty - 1); Text(data->icld_BufferRastPort, buf, nameLength);
453 SetAPen(data->icld_BufferRastPort, data->icld_LabelPen);
454 Move(data->icld_BufferRastPort, tx, ty);
455 Text(data->icld_BufferRastPort, buf, nameLength);
456 SetSoftStyle(data->icld_BufferRastPort, FS_NORMAL, AskSoftStyle(data->icld_BufferRastPort));
457 break;
460 /*date/size sorting has the date/size appended under the icon label*/
462 if( icon->ile_IconListEntry.type != WBDRAWER && ((data->icld_SortFlags & ICONLIST_SORT_BY_SIZE) || (data->icld_SortFlags & ICONLIST_SORT_BY_DATE)) )
464 if( (data->icld_SortFlags & ICONLIST_SORT_BY_SIZE) && !(data->icld_SortFlags & ICONLIST_SORT_BY_DATE) )
466 int i = icon->ile_FileInfoBlock.fib_Size;
468 /*show byte size for small files*/
469 if( i > 9999 )
470 sprintf( buf , "%ld KB" , (LONG)(i/1024) );
471 else
472 sprintf( buf , "%ld B" , (LONG)i );
474 else
476 if( !(data->icld_SortFlags & ICONLIST_SORT_BY_SIZE) && (data->icld_SortFlags & ICONLIST_SORT_BY_DATE) )
478 struct DateStamp now;
479 DateStamp(&now);
481 /*if modified today show time, otherwise just show date*/
482 if( now.ds_Days == icon->ile_FileInfoBlock.fib_Date.ds_Days )
483 sprintf( buf , "%s" ,icon->ile_TxtBuf_TIME );
484 else
485 sprintf( buf , "%s" ,icon->ile_TxtBuf_DATE );
489 nameLength = strlen(buf);
491 ULONG textwidth = TextLength(data->icld_BufferRastPort, buf, nameLength);
492 tx = iconrect.MinX + ((iconrect.MaxX - iconrect.MinX + 1 - textwidth)/2);
493 ty = iconY + icon->ile_IconHeight + data->icld_IconFont->tf_YSize + ICONLIST_TEXTMARGIN + data->icld_IconFont->tf_Baseline;
495 switch ( data->icld__Option_IconTextMode )
497 case ICON_TEXTMODE_DROPSHADOW:
498 case ICON_TEXTMODE_PLAIN:
499 SetAPen(data->icld_BufferRastPort, data->icld_InfoShadowPen);
500 Move(data->icld_BufferRastPort, tx, ty); Text(data->icld_BufferRastPort, buf, nameLength);
501 break;
503 default:
504 // Outline mode..
505 SetSoftStyle(data->icld_BufferRastPort, FSF_BOLD, AskSoftStyle(data->icld_BufferRastPort));
506 SetAPen(data->icld_BufferRastPort, data->icld_InfoShadowPen);
508 Move(data->icld_BufferRastPort, tx + 1, ty ); Text(data->icld_BufferRastPort, buf, nameLength);
509 Move(data->icld_BufferRastPort, tx - 1, ty ); Text(data->icld_BufferRastPort, buf, nameLength);
510 Move(data->icld_BufferRastPort, tx, ty + 1); Text(data->icld_BufferRastPort, buf, nameLength);
511 Move(data->icld_BufferRastPort, tx, ty - 1); Text(data->icld_BufferRastPort, buf, nameLength);
513 SetAPen(data->icld_BufferRastPort, data->icld_InfoPen);
514 Move(data->icld_BufferRastPort, tx, ty);
515 Text(data->icld_BufferRastPort, buf, nameLength);
516 SetSoftStyle(data->icld_BufferRastPort, FS_NORMAL, AskSoftStyle(data->icld_BufferRastPort));
517 break;
520 // Free up icontext memory
521 FreeVec(buf);
524 return TRUE;
527 /**************************************************************************
529 **************************************************************************/
530 static void IconList_RethinkDimensions(Object *obj, struct MUI_IconData *data, struct IconEntry *singleicon)
532 struct IconEntry *icon = NULL;
533 WORD maxx = data->width - 1,
534 maxy = data->height - 1;
536 D(bug("[IconList] IconList_RethinkDimensions()\n"));
538 if (!(_flags(obj)&MADF_SETUP)) return;
540 icon = singleicon ? singleicon : List_First(&data->icld_IconList);
542 while (icon)
544 if (icon->ile_DiskObj &&
545 (icon->ile_Flags & ICONENTRY_FLAG_VISIBLE) &&
546 (icon->ile_IconX != NO_ICON_POSITION) &&
547 (icon->ile_IconY != NO_ICON_POSITION))
549 struct Rectangle icon_rect;
551 IconList_GetIconRectangle(obj, data, icon, &icon_rect);
553 icon_rect.MinX += icon->ile_IconX;
554 icon_rect.MaxX += icon->ile_IconX;
555 icon_rect.MinY += icon->ile_IconY;
556 icon_rect.MaxY += icon->ile_IconY;
558 if (icon_rect.MaxX > maxx) maxx = icon_rect.MaxX;
559 if (icon_rect.MaxY > maxy) maxy = icon_rect.MaxY;
563 if (singleicon) break;
565 icon = Node_Next(icon);
568 /* update our view when max x/y have changed */
569 if (maxx + 1 != data->width)
571 data->width = maxx + 1;
572 SET(obj, MUIA_IconList_Width, data->width);
574 if (maxy + 1 != data->height)
576 data->height = maxy + 1;
577 SET(obj, MUIA_IconList_Height, data->height);
582 /**************************************************************************
583 Checks weather we can place a icon with the given dimesions at the
584 suggested positions.
586 atx and aty are absolute positions
587 **************************************************************************/
589 static int IconList_CouldPlaceIcon(Object *obj, struct MUI_IconData *data, struct IconEntry *toplace, int atx, int aty)
591 struct IconEntry *icon;
592 struct Rectangle toplace_rect;
594 IconList_GetIconRectangle(obj, toplace, &toplace_rect);
595 toplace_rect.MinX += atx;
596 toplace_rect.MaxX += atx;
597 toplace_rect.MinY += aty;
598 toplace_rect.MaxY += aty;
600 icon = List_First(&data->icld_IconList);
601 while (icon)
603 if (icon->ile_DiskObj && icon->ile_IconX != NO_ICON_POSITION && icon->ile_IconY != NO_ICON_POSITION)
605 struct Rectangle icon_rect;
606 IconList_GetIconRectangle(obj, icon, &icon_rect);
607 icon_rect.MinX += icon->ile_IconX;
608 icon_rect.MaxX += icon->ile_IconX;
609 icon_rect.MinY += icon->ile_IconY;
610 icon_rect.MaxY += icon->ile_IconY;
612 if (RectAndRect(&icon_rect, &toplace_rect))
613 return FALSE; *//* There is already an icon on this place *//*
615 icon = Node_Next(icon);
617 return 1;
621 /**************************************************************************
622 Place the icon at atx and aty.
624 atx and aty are absolute positions
625 **************************************************************************/
627 static void IconList_PlaceIcon(Object *obj, struct MUI_IconData *data, struct IconEntry *toplace, int atx, int aty)
629 #if 0
630 struct Rectangle toplace_rect;
632 IconList_GetIconRectangle(obj, toplace, &toplace_rect);
633 toplace_rect.MinX += atx + data->icld_ViewX;
634 toplace_rect.MaxX += atx + data->icld_ViewX;
635 toplace_rect.MinY += aty + data->icld_ViewY;
636 toplace_rect.MaxY += aty + data->icld_ViewY;
637 #endif
638 toplace->x = atx;
639 toplace->y = aty;
640 #if 0
641 *//* update our view *//*
642 if (toplace_rect.MaxX - data->icld_ViewX > data->width)
644 data->width = toplace_rect.MaxX - data->icld_ViewX;
645 SET(obj, MUIA_IconList_Width, data->width);
648 if (toplace_rect.MaxY - data->icld_ViewY > data->height)
650 data->height = toplace_rect.MaxY - data->icld_ViewY;
651 SET(obj, MUIA_IconList_Height, data->height);
653 #endif
656 /**************************************************************************
657 MUIM_PositionIcons - Place icons with NO_ICON_POSITION coords somewhere
658 **************************************************************************/
660 IPTR IconList__MUIM_IconList_PositionIcons(struct IClass *CLASS, Object *obj, struct MUIP_IconList_PositionIcons *message)
662 struct MUI_IconData *data = INST_DATA(CLASS, obj);
663 struct IconEntry *icon = NULL;
665 int spacing = 4;
666 int top = spacing;
667 int left = spacing;
668 int gridx = 32;
669 int gridy = 32;
670 int cur_x = spacing;
671 int cur_y = spacing;
672 int maxw = 0; // There two are the max icon width recorded in a column
673 int maxh = 0; // or the max icon height recorded in a row depending
674 int listMode = (int)data->icld__Option_IconListMode;
676 D(bug("[IconList] IconList__MUIM_IconList_PositionIcons()\n"));
678 BOOL next = TRUE;
679 int maxWidth = 0,
680 maxHeight = 0;
682 // If going by grid, first traverse and find the highest w/h
683 if (listMode == ICON_LISTMODE_GRID)
685 ForeachNode(&data->icld_IconList, icon)
687 if (icon->ile_Flags & ICONENTRY_FLAG_VISIBLE)
689 struct Rectangle iconrect;
691 IconList_GetIconRectangle(obj, data, icon, &iconrect);
693 if ( icon->ile_AreaWidth > maxWidth )
694 maxWidth = icon->ile_AreaWidth;
696 if ( icon->ile_AreaHeight > maxHeight )
697 maxHeight = icon->ile_AreaHeight;
702 // Now go to the actual positioning
703 icon = List_First(&data->icld_IconList);
704 while (icon != NULL)
706 if ((icon->ile_DiskObj != NULL) && (icon->ile_Flags & ICONENTRY_FLAG_VISIBLE))
708 icon->ile_IconX = cur_x;
709 icon->ile_IconY = cur_y;
711 if ( listMode == ICON_LISTMODE_GRID )
713 gridx = maxWidth + spacing;
714 gridy = maxHeight + spacing;
715 // center icons on grid
716 icon->ile_IconX += ( maxWidth - icon->ile_AreaWidth ) / 2;
717 icon->ile_IconY += ( maxHeight - icon->ile_AreaHeight ) / 2;
719 else
721 // Update the realWidth/realHeight values every time we position an icon!
722 struct Rectangle iconrect;
723 IconList_GetIconRectangle(obj, data, icon, &iconrect);
724 gridx = icon->ile_AreaWidth + spacing;
725 gridy = icon->ile_AreaHeight + spacing;
728 if (data->icld_DisplayFlags & ICONLIST_DISP_VERTICAL)
730 if ( maxw < gridx ) maxw = gridx;
731 cur_y += gridy;
733 if (cur_y >= data->icld_ViewHeight )
735 next = FALSE;
736 cur_x += maxw;
737 cur_y = top;
740 else
742 if ( maxh < gridy ) maxh = gridy;
743 cur_x += gridx;
745 if (cur_x >= data->icld_ViewWidth )
747 next = FALSE;
748 cur_x = left;
749 cur_y += maxh;
753 if ( next )
754 icon = Node_Next(icon);
755 next = TRUE;
757 IconList_RethinkDimensions(obj, data, NULL);
758 return 0;
761 /*static void IconList_FixNoPositionIcons(Object *obj, struct MUI_IconData *data)
763 struct IconEntry *icon;
764 int cur_x = data->icld_ViewX + 36;
765 int cur_y = data->icld_ViewY + 4;
767 icon = List_First(&data->icld_IconList);
768 while (icon)
770 if (icon->ile_DiskObj && icon->ile_IconX == NO_ICON_POSITION && icon->ile_IconY == NO_ICON_POSITION)
772 int loops = 0;
773 int cur_x_save = cur_x;
774 int cur_y_save = cur_y;
775 struct Rectangle icon_rect;
777 IconList_GetIconRectangle(obj, icon, &icon_rect);
778 icon_rect.MinX += cur_x - icon->ile_IconWidth/2 + data->icld_ViewX;
779 if (icon_rect.MinX < 0)
780 cur_x -= icon_rect.MinX;
782 while (!IconList_CouldPlaceIcon(obj, data, icon, cur_x - icon->ile_IconWidth/2, cur_y) && loops < 5000)
784 cur_y++;
786 if (cur_y + icon->ile_IconHeight > data->icld_ViewX + data->icld_ViewHeight) *//* on both sides -1 *//*
788 cur_x += 72;
789 cur_y = data->icld_ViewY + 4;
793 IconList_PlaceIcon(obj, data, icon, cur_x - icon->ile_IconWidth/2, cur_y);
795 if (icon_rect.MinX < 0)
797 cur_x = cur_x_save;
798 cur_y = cur_y_save;
801 icon = Node_Next(icon);
804 IconList_RethinkDimensions(obj, data, NULL);
807 /**************************************************************************
808 OM_NEW
809 **************************************************************************/
810 IPTR IconList__OM_NEW(struct IClass *CLASS, Object *obj, struct opSet *message)
812 struct MUI_IconData *data = NULL;
813 struct TextFont *icl_WindowFont = NULL;
814 struct RastPort *icl_RastPort = NULL;
816 icl_WindowFont = (struct TextFont *) GetTagData(MUIA_Font, (IPTR) NULL, message->ops_AttrList);
817 icl_RastPort = (struct RastPort *) GetTagData(MUIA_IconList_Rastport, (IPTR) NULL, message->ops_AttrList);
819 obj = (Object *)DoSuperNewTags(CLASS, obj, NULL,
820 MUIA_FillArea, FALSE,
821 MUIA_Dropable, TRUE,
822 MUIA_Font, MUIV_Font_Tiny,
823 TAG_MORE, (IPTR) message->ops_AttrList);
825 if (!obj) return FALSE;
827 data = INST_DATA(CLASS, obj);
829 data->icld_Pool = CreatePool(0,4096,4096);
830 if (!data->icld_Pool)
832 CoerceMethod(CLASS,obj,OM_DISPOSE);
833 return (IPTR)NULL;
836 D(bug("[IconList] IconList__OM_NEW: SELF = %x\n", obj));
838 data->icld_SelectionLast = NULL;
840 NewList((struct List*)&data->icld_IconList);
842 data->icld_BufferRastPort = icl_RastPort;
843 data->icld_IconFont = icl_WindowFont;
845 // Get some initial values
846 data->icld__Option_IconListMode = (UBYTE)GetTagData(MUIA_IconList_ListMode, 0, message->ops_AttrList);
847 data->icld__Option_IconTextMode = (UBYTE)GetTagData(MUIA_IconList_TextMode, 0, message->ops_AttrList);
848 data->icld__Option_IconTextMaxLen = GetTagData(MUIA_IconList_TextMaxLen, 0, message->ops_AttrList);
850 if ( data->icld__Option_IconTextMaxLen <= 0 )
851 data->icld__Option_IconTextMaxLen = ICON_TEXTMAXLEN_DEFAULT;
853 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY;
854 data->ehn.ehn_Priority = 0;
855 data->ehn.ehn_Flags = 0;
856 data->ehn.ehn_Object = obj;
857 data->ehn.ehn_Class = CLASS;
859 data->icld_SortFlags = 0;
860 data->icld_DisplayFlags = ICONLIST_DISP_SHOWINFO;
862 return (IPTR)obj;
865 /**************************************************************************
866 OM_DISPOSE
867 **************************************************************************/
868 IPTR IconList__OM_DISPOSE(struct IClass *CLASS, Object *obj, Msg message)
870 struct MUI_IconData *data = INST_DATA(CLASS, obj);
871 struct IconEntry *node = NULL;
873 ForeachNode(&data->icld_IconList, node)
875 if (node->ile_DiskObj) FreeDiskObject(node->ile_DiskObj);
878 if (data->icld_Pool) DeletePool(data->icld_Pool);
880 DoSuperMethodA(CLASS,obj,message);
881 return 0;
885 /**************************************************************************
886 OM_SET
887 **************************************************************************/
888 IPTR IconList__OM_SET(struct IClass *CLASS, Object *obj, struct opSet *message)
890 struct MUI_IconData *data = INST_DATA(CLASS, obj);
891 struct TagItem *tag = NULL,
892 *tags = NULL;
894 WORD oldleft = data->icld_ViewX,
895 oldtop = data->icld_ViewY,
896 oldwidth = data->icld_ViewWidth,
897 oldheight = data->icld_ViewHeight;
899 /* parse initial taglist */
900 for (tags = message->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
902 switch (tag->ti_Tag)
904 case MUIA_IconList_Left:
905 if (data->icld_ViewX != tag->ti_Data)
906 data->icld_ViewX = tag->ti_Data;
907 break;
909 case MUIA_IconList_Top:
910 if (data->icld_ViewY != tag->ti_Data)
911 data->icld_ViewY = tag->ti_Data;
912 break;
914 case MUIA_IconList_Rastport:
915 data->icld_BufferRastPort = (struct RastPort*)tag->ti_Data;
916 break;
918 case MUIA_Font:
919 data->icld_IconFont = (struct TextFont*)tag->ti_Data;
920 break;
922 case MUIA_IconList_DisplayFlags:
923 data->icld_DisplayFlags = tag->ti_Data;
924 break;
926 case MUIA_IconList_SortFlags:
927 data->icld_SortFlags = tag->ti_Data;
928 break;
930 case MUIA_IconList_ListMode:
931 data->icld__Option_IconListMode = (UBYTE)tag->ti_Data;
932 break;
934 case MUIA_IconList_TextMode:
935 data->icld__Option_IconTextMode = (UBYTE)tag->ti_Data;
936 break;
938 case MUIA_IconList_TextMaxLen:
939 data->icld__Option_IconTextMaxLen = tag->ti_Data;
940 break;
942 /* Settings defined by the view class */
943 case MUIA_IconListview_FixedBackground:
944 data->icld__Option_IconListFixedBackground = (BOOL)tag->ti_Data;
945 break;
947 case MUIA_IconListview_ScaledBackground:
948 data->icld__Option_IconListScaledBackground = (BOOL)tag->ti_Data;
949 break;
951 /* We also listen for this and manually adjust for known stuff */
952 case MUIA_Background:
953 D(bug("[IconList] IconList__OM_SET: MUIA_Background\n"));
955 char *bgmode_string = tag->ti_Data;
956 BYTE this_mode = bgmode_string[0] - 48;
958 D(bug("[IconList] IconList__OM_SET: MUIA_Background | MUI BG Mode = %d\n", this_mode));
959 switch (this_mode)
961 case 0:
962 //MUI Pattern
963 data->icld__Option_IconListFixedBackground = FALSE;
964 data->icld__Option_IconListScaledBackground = FALSE;
965 break;
966 case 2:
967 //MUI RGB color
968 data->icld__Option_IconListFixedBackground = FALSE;
969 data->icld__Option_IconListScaledBackground = FALSE;
970 break;
971 case 7:
972 //Zune Gradient
973 data->icld__Option_IconListFixedBackground = TRUE;
974 data->icld__Option_IconListScaledBackground = TRUE;
975 break;
976 case 5:
977 //Image
978 data->icld__Option_IconListFixedBackground = FALSE;
979 data->icld__Option_IconListScaledBackground = FALSE;
980 break;
982 return 0;
987 if ((oldleft != data->icld_ViewX) || (oldtop != data->icld_ViewY))
989 data->icld_UpdateMode = UPDATE_SCROLL;
990 data->update_scrolldx = data->icld_ViewX - oldleft;
991 data->update_scrolldy = data->icld_ViewY - oldtop;
992 MUI_Redraw(obj, MADF_DRAWUPDATE);
995 return DoSuperMethodA(CLASS, obj, (Msg)message);
998 /**************************************************************************
999 OM_GET
1000 **************************************************************************/
1001 IPTR IconList__OM_GET(struct IClass *CLASS, Object *obj, struct opGet *message)
1003 /* small macro to simplify return value storage */
1004 #define STORE *(message->opg_Storage)
1005 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1007 switch (message->opg_AttrID)
1009 case MUIA_IconList_Rastport: STORE = data->icld_BufferRastPort; return 1;
1010 case MUIA_IconList_Left: STORE = data->icld_ViewX; return 1;
1011 case MUIA_IconList_Top: STORE = data->icld_ViewY; return 1;
1012 case MUIA_IconList_Width: STORE = data->width; return 1;
1013 case MUIA_IconList_Height: STORE = data->height; return 1;
1014 case MUIA_IconList_IconsDropped: STORE = (IPTR)&data->drop_entry; return 1;
1015 case MUIA_IconList_Clicked: STORE = (ULONG)&data->icon_click; return 1;
1016 case MUIA_IconList_ListMode: STORE = (ULONG)data->icld__Option_IconListMode; return 1;
1017 case MUIA_IconList_TextMode: STORE = (ULONG)data->icld__Option_IconTextMode; return 1;
1018 case MUIA_IconList_TextMaxLen: STORE = (ULONG)data->icld__Option_IconTextMaxLen; return 1;
1019 case MUIA_IconList_DisplayFlags: STORE = data->icld_DisplayFlags; return 1;
1020 case MUIA_IconList_SortFlags: STORE = data->icld_SortFlags; return 1;
1022 /* Settings defined by the view class */
1023 case MUIA_IconListview_FixedBackground: STORE = (IPTR)data->icld__Option_IconListFixedBackground; return 1;
1024 case MUIA_IconListview_ScaledBackground: STORE = (IPTR)data->icld__Option_IconListScaledBackground; return 1;
1027 if (DoSuperMethodA(CLASS, obj, (Msg) message))
1028 return 1;
1029 return 0;
1030 #undef STORE
1033 /**************************************************************************
1034 MUIM_Setup
1035 **************************************************************************/
1036 IPTR IconList__MUIM_Setup(struct IClass *CLASS, Object *obj, struct MUIP_Setup *message)
1038 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1039 struct IconEntry *node = NULL;
1041 if (!DoSuperMethodA(CLASS, obj, (Msg) message)) return 0;
1043 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
1045 /* Get Internal Objects to use if not set .. */
1046 if (data->icld_BufferRastPort == NULL) data->icld_BufferRastPort = _rp(obj);
1047 if (data->icld_IconFont == NULL) data->icld_IconFont = _font(obj);
1048 D(bug("[IconList] IconList__MUIM_Setup: Use Font @ %x, RastPort @ %x\n", data->icld_IconFont, data->icld_BufferRastPort ));
1050 /* Set our base options .. */
1051 data->icld_LabelPen = _pens(obj)[MPEN_SHINE];
1052 data->icld_LabelShadowPen = _pens(obj)[MPEN_SHADOW];
1053 data->icld_InfoPen = _pens(obj)[MPEN_SHINE];
1054 data->icld_InfoShadowPen = _pens(obj)[MPEN_SHADOW];
1056 ForeachNode(&data->icld_IconList, node)
1058 if (!node->ile_DiskObj)
1060 if (!(node->ile_DiskObj = GetIconTags(node->ile_IconListEntry.filename, ICONGETA_FailIfUnavailable, FALSE, ICONGETA_Label, (IPTR) node->ile_IconListEntry.label, TAG_DONE)))
1062 D(bug("[IconList] IconList__MUIM_Setup: Failed to obtain Icon '%s's diskobj!!\n", node->ile_IconListEntry.filename));
1063 /* We should proabbly remove this node if the icon cant be obtained ? */
1067 return 1;
1070 /**************************************************************************
1071 MUIM_Show
1072 **************************************************************************/
1073 IPTR IconList__MUIM_Show(struct IClass *CLASS, Object *obj, struct MUIP_Show *message)
1075 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1076 LONG newleft,
1077 newtop;
1078 IPTR rc;
1080 if (rc = DoSuperMethodA(CLASS, obj, (Msg)message))
1083 newleft = data->icld_ViewX;
1084 newtop = data->icld_ViewY;
1086 if (newleft + _mwidth(obj) > data->width) newleft = data->width - _mwidth(obj);
1087 if (newleft < 0) newleft = 0;
1089 if (newtop + _mheight(obj) > data->height) newtop = data->height - _mheight(obj);
1090 if (newtop < 0) newtop = 0;
1092 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
1094 SetAttrs(obj, MUIA_IconList_Left, newleft,
1095 MUIA_IconList_Top, newtop,
1096 TAG_DONE);
1099 /* Get Internal Objects to use if not set .. */
1100 if (data->icld_BufferRastPort == NULL) data->icld_BufferRastPort = _rp(obj);
1101 if (data->icld_IconFont == NULL) data->icld_IconFont = _font(obj);
1102 D(bug("[IconList] IconList__MUIM_Show: Use Font @ %x, RastPort @ %x\n", data->icld_IconFont, data->icld_BufferRastPort ));
1104 if ((data->icld_BufferRastPort) && (data->icld_IconFont))
1105 SetFont(data->icld_BufferRastPort, data->icld_IconFont);
1107 return rc;
1111 /**************************************************************************
1112 MUIM_Cleanup
1113 **************************************************************************/
1114 IPTR IconList__MUIM_Cleanup(struct IClass *CLASS, Object *obj, struct MUIP_Cleanup *message)
1116 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1117 struct IconEntry *node = NULL;
1119 ForeachNode(&data->icld_IconList, node)
1121 if (node->ile_DiskObj)
1123 FreeDiskObject(node->ile_DiskObj);
1124 node->ile_DiskObj = NULL;
1128 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1130 return DoSuperMethodA(CLASS, obj, (Msg)message);
1133 /**************************************************************************
1134 MUIM_AskMinMax
1135 **************************************************************************/
1136 IPTR IconList__MUIM_AskMinMax(struct IClass *CLASS, Object *obj, struct MUIP_AskMinMax *message)
1138 ULONG rc = DoSuperMethodA(CLASS, obj, (Msg) message);
1140 message->MinMaxInfo->MinWidth += 96;
1141 message->MinMaxInfo->MinHeight += 64;
1143 message->MinMaxInfo->DefWidth += 200;
1144 message->MinMaxInfo->DefHeight += 180;
1146 message->MinMaxInfo->MaxWidth = MUI_MAXMAX;
1147 message->MinMaxInfo->MaxHeight = MUI_MAXMAX;
1149 return rc;
1152 /**************************************************************************
1153 MUIM_Layout
1154 **************************************************************************/
1155 IPTR IconList__MUIM_Layout(struct IClass *CLASS, Object *obj,struct MUIP_Layout *message)
1157 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1159 ULONG rc = DoSuperMethodA(CLASS, obj, (Msg)message);
1161 data->icld_ViewWidth = _mwidth(obj);
1162 data->icld_ViewHeight = _mheight(obj);
1164 return rc;
1167 /**************************************************************************
1168 MUIM_Draw - draw the IconList
1169 **************************************************************************/
1170 IPTR IconList__MUIM_Draw(struct IClass *CLASS, Object *obj, struct MUIP_Draw *message)
1172 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1173 struct IconEntry *icon = NULL;
1175 APTR clip;
1177 ULONG update_oldwidth = 0,
1178 update_oldheight = 0;
1180 LONG clear_xoffset = 0,
1181 clear_yoffset = 0;
1183 DoSuperMethodA(CLASS, obj, (Msg)message);
1185 if (!data->icld__Option_IconListFixedBackground)
1187 clear_xoffset = data->icld_ViewX;
1188 clear_yoffset = data->icld_ViewY;
1191 // If window size changes, only update needed areas
1192 if (data->update_oldwidth == 0) data->update_oldwidth = data->icld_ViewWidth;
1193 if (data->update_oldheight == 0) data->update_oldheight = data->icld_ViewHeight;
1194 if (data->update_oldwidth != data->icld_ViewWidth || data->update_oldheight != data->icld_ViewHeight)
1196 if ( data->icld_UpdateMode != UPDATE_SCROLL )
1198 data->icld_UpdateMode = UPDATE_RESCALE;
1199 update_oldwidth = data->update_oldwidth;
1200 update_oldheight = data->update_oldheight;
1201 data->update_oldwidth = data->icld_ViewWidth;
1202 data->update_oldheight = data->icld_ViewHeight;
1206 if (message->flags & MADF_DRAWUPDATE || data->icld_UpdateMode == UPDATE_RESCALE)
1208 if (data->icld_UpdateMode == UPDATE_SINGLEICON) /* draw only a single icon at update_icon */
1210 struct Rectangle rect;
1212 IconList_GetIconRectangle(obj, data, data->update_icon, &rect);
1214 rect.MinX += _mleft(obj) + (data->update_icon->ile_IconX - data->icld_ViewX);
1215 rect.MaxX += _mleft(obj) + (data->update_icon->ile_IconX - data->icld_ViewX);
1216 rect.MinY += _mtop(obj) + (data->update_icon->ile_IconY - data->icld_ViewY);
1217 rect.MaxY += _mtop(obj) + (data->update_icon->ile_IconY - data->icld_ViewY);
1219 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj));
1221 D(bug("[IconList] IconList__MUIM_Draw: Calling MUIM_DrawBackground (A)\n"));
1222 DoMethod(obj, MUIM_DrawBackground,
1223 rect.MinX, rect.MinY,
1224 rect.MaxX - rect.MinX + 1, rect.MaxY - rect.MinY + 1,
1225 clear_xoffset, clear_yoffset,
1228 /* We could have deleted also other icons so they must be redrawn */
1229 ForeachNode(&data->icld_IconList, icon)
1231 if ((icon != data->update_icon) && (icon->ile_Flags & ICONENTRY_FLAG_VISIBLE))
1233 struct Rectangle rect2;
1234 IconList_GetIconRectangle(obj, data, icon, &rect2);
1236 rect2.MinX += _mleft(obj) - data->icld_ViewX + icon->ile_IconX;
1237 rect2.MaxX += _mleft(obj) - data->icld_ViewX + icon->ile_IconX;
1238 rect2.MinY += _mtop(obj) - data->icld_ViewY + icon->ile_IconY;
1239 rect2.MaxY += _mtop(obj) - data->icld_ViewY + icon->ile_IconY;
1241 if (RectAndRect(&rect,&rect2))
1243 // Update icon here
1244 IconList_DrawIcon(obj, data, icon, DRAWICON_DODRAW);
1249 IconList_DrawIcon(obj, data, data->update_icon, DRAWICON_DODRAW);
1250 data->icld_UpdateMode = 0;
1251 MUI_RemoveClipping(muiRenderInfo(obj),clip);
1252 return 0;
1254 else if (data->icld_UpdateMode == UPDATE_SCROLL)
1256 struct Region *region = NULL;
1257 struct Rectangle xrect,
1258 yrect;
1259 BOOL scroll_caused_damage;
1261 if (!data->icld__Option_IconListFixedBackground)
1263 scroll_caused_damage = (_rp(obj)->Layer->Flags & LAYERREFRESH) ? FALSE : TRUE;
1265 data->icld_UpdateMode = 0;
1267 if ((abs(data->update_scrolldx) >= _mwidth(obj)) ||
1268 (abs(data->update_scrolldy) >= _mheight(obj)))
1270 MUI_Redraw(obj, MADF_DRAWOBJECT);
1271 return 0;
1274 if (!(region = NewRegion()))
1276 MUI_Redraw(obj, MADF_DRAWOBJECT);
1277 return 0;
1280 if (data->update_scrolldx > 0)
1282 xrect.MinX = _mright(obj) - data->update_scrolldx;
1283 xrect.MinY = _mtop(obj);
1284 xrect.MaxX = _mright(obj);
1285 xrect.MaxY = _mbottom(obj);
1287 OrRectRegion(region, &xrect);
1289 data->update_rect1 = &xrect;
1291 else if (data->update_scrolldx < 0)
1293 xrect.MinX = _mleft(obj);
1294 xrect.MinY = _mtop(obj);
1295 xrect.MaxX = _mleft(obj) - data->update_scrolldx;
1296 xrect.MaxY = _mbottom(obj);
1298 OrRectRegion(region, &xrect);
1300 data->update_rect1 = &xrect;
1303 if (data->update_scrolldy > 0)
1305 yrect.MinX = _mleft(obj);
1306 yrect.MinY = _mbottom(obj) - data->update_scrolldy;
1307 yrect.MaxX = _mright(obj);
1308 yrect.MaxY = _mbottom(obj);
1310 OrRectRegion(region, &yrect);
1312 data->update_rect2 = &yrect;
1314 else if (data->update_scrolldy < 0)
1316 yrect.MinX = _mleft(obj);
1317 yrect.MinY = _mtop(obj);
1318 yrect.MaxX = _mright(obj);
1319 yrect.MaxY = _mtop(obj) - data->update_scrolldy;
1321 OrRectRegion(region, &yrect);
1323 data->update_rect2 = &yrect;
1326 ScrollRasterBF(data->icld_BufferRastPort,
1327 data->update_scrolldx,
1328 data->update_scrolldy,
1329 _mleft(obj),
1330 _mtop(obj),
1331 _mright(obj),
1332 _mbottom(obj));
1334 scroll_caused_damage = scroll_caused_damage && (_rp(obj)->Layer->Flags & LAYERREFRESH) ? TRUE : FALSE;
1336 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1339 MUI_Redraw(obj, MADF_DRAWOBJECT);
1341 data->update_rect1 = data->update_rect2 = NULL;
1343 if (!data->icld__Option_IconListFixedBackground)
1345 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1347 if (scroll_caused_damage)
1349 if (MUI_BeginRefresh(muiRenderInfo(obj), 0))
1351 /* Theoretically it might happen that more damage is caused
1352 after ScrollRaster. By something else, like window movement
1353 in front of our window. Therefore refresh root object of
1354 window, not just this object */
1356 Object *o = NULL;
1358 GET(_win(obj),MUIA_Window_RootObject, &o);
1359 MUI_Redraw(o, MADF_DRAWOBJECT);
1361 MUI_EndRefresh(muiRenderInfo(obj), 0);
1365 return 0;
1367 else if (data->icld_UpdateMode == UPDATE_RESCALE)
1369 struct Region *region = NULL;
1370 struct Rectangle wrect,
1371 hrect;
1372 ULONG diffw = 0,
1373 diffh = 0;
1375 data->icld_UpdateMode = 0;
1377 if (!data->icld__Option_IconListScaledBackground)
1379 if (!(region = NewRegion()))
1381 MUI_Redraw(obj, MADF_DRAWOBJECT);
1382 return 0;
1385 if ( data->icld_ViewWidth > update_oldwidth )
1386 diffw = data->icld_ViewWidth - update_oldwidth;
1387 if ( data->icld_ViewHeight > update_oldheight )
1388 diffh = data->icld_ViewHeight - update_oldheight;
1390 if (diffw)
1392 wrect.MinX = _mright(obj) - diffw;
1393 wrect.MinY = _mtop(obj);
1394 wrect.MaxX = _mright(obj);
1395 wrect.MaxY = _mbottom(obj);
1396 OrRectRegion(region, &wrect);
1397 data->update_rect1 = &wrect;
1400 if (diffh)
1402 hrect.MinX = _mleft(obj);
1403 hrect.MinY = _mbottom(obj) - diffh;
1404 hrect.MaxX = _mright(obj);
1405 hrect.MaxX = _mright(obj);
1406 hrect.MaxY = _mbottom(obj);
1407 OrRectRegion(region, &hrect);
1408 data->update_rect2 = &hrect;
1410 if (diffh||diffw)
1412 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1414 else
1416 /* View became smaller both in horizontal and vertical direction.
1417 Nothing to do */
1419 DisposeRegion(region);
1420 return 0;
1424 MUI_Redraw(obj, MADF_DRAWOBJECT);
1426 if (!data->icld__Option_IconListScaledBackground)
1428 if (diffh||diffw)
1430 data->update_rect1 = data->update_rect2 = NULL;
1431 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
1432 } else DisposeRegion(region);
1435 return 0;
1439 /* At we see if there any Icons without proper position, this is the wrong place here,
1440 * it should be done after all icons have been loaded */
1442 /*ric - no need!: IconList_FixNoPositionIcons(obj, data);*/
1443 if (message->flags & MADF_DRAWOBJECT)
1445 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj));
1447 D(bug("[IconList] IconList__MUIM_Draw: Calling MUIM_DrawBackground (B)\n"));
1448 DoMethod(
1449 obj, MUIM_DrawBackground, _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj),
1450 clear_xoffset, clear_yoffset, 0
1453 ForeachNode(&data->icld_IconList, icon)
1455 if ((icon->ile_Flags & ICONENTRY_FLAG_VISIBLE) && (icon->ile_DiskObj && icon->ile_IconX != NO_ICON_POSITION && icon->ile_IconY != NO_ICON_POSITION))
1457 IconList_DrawIcon(obj, data, icon, DRAWICON_DODRAW);
1461 MUI_RemoveClipping(muiRenderInfo(obj), clip);
1463 data->icld_UpdateMode = 0;
1465 return 0;
1468 /**************************************************************************
1469 MUIM_IconList_Refresh
1470 Implemented by subclasses
1471 **************************************************************************/
1472 IPTR IconList__MUIM_IconList_Update(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Update *message)
1474 return 1;
1477 /**************************************************************************
1478 MUIM_IconList_Clear
1479 **************************************************************************/
1480 IPTR IconList__MUIM_IconList_Clear(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Clear *message)
1482 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1483 struct IconEntry *node = NULL;
1485 while ((node = (struct IconEntry*)RemTail((struct List*)&data->icld_IconList)))
1487 DoMethod(obj, MUIM_IconList_DestroyEntry, node);
1490 data->icld_SelectionFirst = NULL;
1491 data->icld_ViewX = data->icld_ViewY = data->width = data->height = 0;
1492 /*data->icld_SortFlags = 0;*/
1494 data->icld_IconLargestWidth = data->icld_IconLargestHeight = 32; /*default icon size*/
1496 SetAttrs(obj, MUIA_IconList_Left, data->icld_ViewX,
1497 MUIA_IconList_Top, data->icld_ViewY,
1498 MUIA_IconList_Width, data->width,
1499 MUIA_IconList_Height, data->height,
1500 TAG_DONE);
1502 MUI_Redraw(obj,MADF_DRAWOBJECT);
1503 return 1;
1506 IPTR IconList__MUIM_IconList_DestroyEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_DestroyEntry *message)
1508 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1510 if (message->icon)
1512 if (message->icon->ile_TxtBuf_PROT) FreePooled(data->icld_Pool, message->icon->ile_TxtBuf_PROT, 8);
1513 if (message->icon->ile_TxtBuf_SIZE) FreePooled(data->icld_Pool, message->icon->ile_TxtBuf_SIZE, 30);
1514 if (message->icon->ile_TxtBuf_TIME) FreePooled(data->icld_Pool, message->icon->ile_TxtBuf_TIME, LEN_DATSTRING);
1515 if (message->icon->ile_TxtBuf_DATE) FreePooled(data->icld_Pool, message->icon->ile_TxtBuf_DATE, LEN_DATSTRING);
1516 if (message->icon->ile_DiskObj) FreeDiskObject(message->icon->ile_DiskObj);
1517 if (message->icon->ile_IconListEntry.label) FreePooled(data->icld_Pool, message->icon->ile_IconListEntry.label, strlen(message->icon->ile_IconListEntry.label)+1);
1518 if (message->icon->ile_IconListEntry.filename) FreePooled(data->icld_Pool, message->icon->ile_IconListEntry.filename, strlen(message->icon->ile_IconListEntry.filename)+1);
1519 FreePooled(data->icld_Pool, message->icon, sizeof(struct IconEntry));
1521 return TRUE;
1524 /**************************************************************************
1525 MUIM_IconList_CreateEntry.
1526 Returns 0 on failure otherwise it returns the icons entry ..
1527 **************************************************************************/
1528 IPTR IconList__MUIM_IconList_CreateEntry(struct IClass *CLASS, Object *obj, struct MUIP_IconList_CreateEntry *message)
1530 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1531 struct IconEntry *entry = NULL;
1532 struct DateTime dt;
1533 UBYTE *sp = NULL;
1535 struct DiskObject *dob = NULL;
1536 struct Rectangle rect;
1538 /*disk object (icon)*/
1539 if (!(message->icon_dob))
1541 dob = GetIconTags
1543 message->filename,
1544 ICONGETA_FailIfUnavailable, FALSE,
1545 ICONGETA_Label, (IPTR) message->label,
1546 TAG_DONE
1549 else
1551 dob = message->icon_dob;
1554 if (!dob) return 0;
1556 if (!(entry = AllocPooled(data->icld_Pool,sizeof(struct IconEntry))))
1558 FreeDiskObject(dob);
1559 return 0;
1562 memset(entry,0,sizeof(struct IconEntry));
1564 /* Allocate Text Buffers */
1565 if (!(entry->ile_TxtBuf_DATE = AllocPooled(data->icld_Pool, LEN_DATSTRING)))
1567 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
1568 return 0;
1570 if (!(entry->ile_TxtBuf_TIME = AllocPooled(data->icld_Pool, LEN_DATSTRING)))
1572 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
1573 return 0;
1575 if (!(entry->ile_TxtBuf_SIZE = AllocPooled(data->icld_Pool, 30)))
1577 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
1578 return 0;
1580 if (!(entry->ile_TxtBuf_PROT = AllocPooled(data->icld_Pool, 8)))
1582 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
1583 return 0;
1586 /*alloc filename*/
1587 if (!(entry->ile_IconListEntry.filename = AllocPooled(data->icld_Pool, strlen(message->filename)+1)))
1589 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
1590 return 0;
1593 /*alloc icon label*/
1594 if (!(entry->ile_IconListEntry.label = AllocPooled(data->icld_Pool,strlen(message->label)+1)))
1596 DoMethod(obj, MUIM_IconList_DestroyEntry, entry);
1597 return 0;
1600 /*file info block*/
1601 if( message->fib )
1603 entry->ile_FileInfoBlock = *message->fib;
1605 if (entry->ile_FileInfoBlock.fib_DirEntryType > 0)
1607 strcpy(entry->ile_TxtBuf_SIZE, "Drawer");
1609 else
1611 sprintf(entry->ile_TxtBuf_SIZE, "%ld", entry->ile_FileInfoBlock.fib_Size);
1614 dt.dat_Stamp = entry->ile_FileInfoBlock.fib_Date;
1615 dt.dat_Format = FORMAT_DEF;
1616 dt.dat_Flags = 0;
1617 dt.dat_StrDay = NULL;
1618 dt.dat_StrDate = entry->ile_TxtBuf_DATE;
1619 dt.dat_StrTime = entry->ile_TxtBuf_TIME;
1621 DateToStr(&dt);
1623 sp = entry->ile_TxtBuf_PROT;
1624 *sp++ = (entry->ile_FileInfoBlock.fib_Protection & FIBF_SCRIPT) ? 's' : '-';
1625 *sp++ = (entry->ile_FileInfoBlock.fib_Protection & FIBF_PURE) ? 'p' : '-';
1626 *sp++ = (entry->ile_FileInfoBlock.fib_Protection & FIBF_ARCHIVE) ? 'a' : '-';
1627 *sp++ = (entry->ile_FileInfoBlock.fib_Protection & FIBF_READ) ? '-' : 'r';
1628 *sp++ = (entry->ile_FileInfoBlock.fib_Protection & FIBF_WRITE) ? '-' : 'w';
1629 *sp++ = (entry->ile_FileInfoBlock.fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
1630 *sp++ = (entry->ile_FileInfoBlock.fib_Protection & FIBF_DELETE) ? '-' : 'd';
1631 *sp++ = '\0';
1633 entry->ile_IconListEntry.type = entry->ile_FileInfoBlock.fib_DirEntryType;
1635 else
1637 entry->ile_IconListEntry.type = ST_USERDIR;
1640 strcpy(entry->ile_IconListEntry.filename,message->filename);
1641 strcpy(entry->ile_IconListEntry.label,message->label);
1643 entry->ile_DiskObj = dob;
1644 entry->ile_IconListEntry.udata = NULL;
1645 entry->ile_IconX = dob->do_CurrentX;
1646 entry->ile_IconY = dob->do_CurrentY;
1648 /* Use a geticonrectangle routine that gets textwidth! */
1649 IconList_GetIconRectangle(obj, data, entry, &rect);
1651 entry->ile_IconWidth = rect.MaxX - rect.MinX + 1;
1652 entry->ile_IconHeight = rect.MaxY - rect.MinY + 1;
1654 //D(bug("add %s %i\n" , entry->ile_IconListEntry.label , (entry->ile_IconListEntry.type & 255) ));
1656 /*hack, force grid to recognise largest icon!*/
1657 if( entry->ile_IconWidth > data->icld_IconLargestWidth ) data->icld_IconLargestWidth = entry->ile_IconWidth;
1658 if( entry->ile_IconHeight > data->icld_IconLargestHeight ) data->icld_IconLargestHeight = entry->ile_IconHeight;
1660 AddHead((struct List*)&data->icld_IconList, (struct Node*)entry);
1662 return entry;
1664 /* fib_DirEntryType,ST_USERDIR; LONG type */
1666 static void DoWheelMove(struct IClass *CLASS, Object *obj, LONG wheelx, LONG wheely, UWORD qual)
1668 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1670 LONG newleft = data->icld_ViewX,
1671 newtop = data->icld_ViewY;
1673 /* Use horizontal scrolling if any of the following cases are true ...
1675 # vertical wheel is used but there's nothing to scroll
1676 (everything is visible already) ..
1678 # vertical wheel is used and one of the ALT keys is down. */
1680 if ((wheely && !wheelx) &&
1681 ((data->height <= _mheight(obj)) || (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))))
1683 wheelx = wheely; wheely = 0;
1686 if (qual & (IEQUALIFIER_CONTROL))
1688 if (wheelx < 0) newleft = 0;
1689 if (wheelx > 0) newleft = data->width;
1690 if (wheely < 0) newtop = 0;
1691 if (wheely > 0) newtop = data->height;
1693 else if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
1695 newleft += (wheelx * _mwidth(obj));
1696 newtop += (wheely * _mheight(obj));
1698 else
1700 newleft += wheelx * 30;
1701 newtop += wheely * 30;
1704 if (newleft + _mwidth(obj) > data->width) newleft = data->width - _mwidth(obj);
1705 if (newleft < 0) newleft = 0;
1707 if (newtop + _mheight(obj) > data->height) newtop = data->height - _mheight(obj);
1708 if (newtop < 0) newtop = 0;
1710 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
1712 SetAttrs(obj, MUIA_IconList_Left, newleft,
1713 MUIA_IconList_Top, newtop,
1714 TAG_DONE);
1719 /**************************************************************************
1720 MUIM_HandleEvent
1721 **************************************************************************/
1722 IPTR IconList__MUIM_HandleEvent(struct IClass *CLASS, Object *obj, struct MUIP_HandleEvent *message)
1724 struct MUI_IconData *data = INST_DATA(CLASS, obj);
1726 if (message->imsg)
1728 LONG mx = message->imsg->MouseX - _mleft(obj);
1729 LONG my = message->imsg->MouseY - _mtop(obj);
1731 LONG wheelx = 0;
1732 LONG wheely = 0;
1734 switch (message->imsg->Class)
1736 case IDCMP_RAWKEY:
1738 BOOL rawkey_handled = FALSE;
1740 switch(message->imsg->Code)
1742 case RAWKEY_NM_WHEEL_UP:
1743 wheely = -1;
1744 rawkey_handled = TRUE;
1745 break;
1747 case RAWKEY_NM_WHEEL_DOWN:
1748 wheely = 1;
1749 rawkey_handled = TRUE;
1750 break;
1752 case RAWKEY_NM_WHEEL_LEFT:
1753 wheelx = -1;
1754 rawkey_handled = TRUE;
1755 break;
1757 case RAWKEY_NM_WHEEL_RIGHT:
1758 wheelx = 1;
1759 rawkey_handled = TRUE;
1760 break;
1763 if (rawkey_handled)
1765 D(bug("[IconList] IconList__MUIM_HandleEvent: Processing mouse wheel event\n"));
1766 if (_isinobject(message->imsg->MouseX, message->imsg->MouseY) &&
1767 (wheelx || wheely))
1769 DoWheelMove(CLASS, obj, wheelx, wheely, message->imsg->Qualifier);
1772 else if (!(message->imsg->Code & 0x80))
1774 LONG new_ViewY = data->icld_ViewY;
1776 D(bug("[IconList] IconList__MUIM_HandleEvent: Processing key up event\n"));
1778 switch(message->imsg->Code)
1780 case RAWKEY_RETURN:
1781 //'ENTER' key pressed
1782 rawkey_handled = TRUE;
1783 break;
1785 case RAWKEY_PAGEUP:
1786 //'PAGE UP' key pressed
1787 rawkey_handled = TRUE;
1789 if (data->height > data->icld_ViewHeight)
1791 new_ViewY -= data->icld_ViewHeight;
1792 if (new_ViewY< 0)
1793 new_ViewY = 0;
1796 if (new_ViewY != data->icld_ViewY)
1798 SET(obj, MUIA_IconList_Top, new_ViewY);
1800 break;
1802 case RAWKEY_PAGEDOWN:
1803 //'PAGE DOWN' key pressed
1804 rawkey_handled = TRUE;
1806 if (data->height > data->icld_ViewHeight)
1808 new_ViewY += data->icld_ViewHeight;
1809 if (new_ViewY > (data->height - data->icld_ViewHeight))
1810 new_ViewY = data->height - data->icld_ViewHeight;
1813 if (new_ViewY != data->icld_ViewY)
1815 SET(obj, MUIA_IconList_Top, new_ViewY);
1817 break;
1819 case RAWKEY_UP:
1820 //'UP CURSOR' key pressed
1821 rawkey_handled = TRUE;
1822 break;
1824 case RAWKEY_DOWN:
1825 //'DOWN CURSOR' key pressed
1826 rawkey_handled = TRUE;
1827 break;
1829 case RAWKEY_LEFT:
1830 //'LEFT CURSOR' key pressed
1831 rawkey_handled = TRUE;
1832 break;
1834 case RAWKEY_RIGHT:
1835 //'RIGHT CURSOR' key pressed
1836 rawkey_handled = TRUE;
1837 break;
1839 case RAWKEY_HOME:
1840 //'HOME' key pressed
1841 rawkey_handled = TRUE;
1842 break;
1844 case RAWKEY_END:
1845 //'END' key pressed
1846 rawkey_handled = TRUE;
1847 break;
1850 if (rawkey_handled) return MUI_EventHandlerRC_Eat;
1852 break;
1854 case IDCMP_MOUSEBUTTONS:
1856 if (message->imsg->Code == SELECTDOWN)
1858 /* check if mouse pressed on iconlist area */
1859 if (mx >= 0 && mx < _width(obj) && my >= 0 && my < _height(obj))
1861 struct IconEntry *node = NULL;
1862 struct IconEntry *new_selected = NULL;
1864 int selections = 0;
1866 data->icld_SelectionFirst = NULL;
1868 /* check if clicked on icon */
1869 ForeachNode(&data->icld_IconList, node)
1871 if (node->ile_Flags & ICONENTRY_FLAG_VISIBLE)
1873 /* count all OLD selections */
1874 if (node->ile_Flags & ICONENTRY_FLAG_SELECTED) selections++;
1876 if (((mx + data->icld_ViewX) >= node->ile_IconX && (mx + data->icld_ViewX) < node->ile_IconX + node->ile_AreaWidth) &&
1877 ((my + data->icld_ViewY) >= node->ile_IconY && (my + data->icld_ViewY) < node->ile_IconY + node->ile_AreaHeight) &&
1878 !new_selected)
1880 new_selected = node;
1882 if (!(node->ile_Flags & ICONENTRY_FLAG_SELECTED))
1884 node->ile_Flags |= ICONENTRY_FLAG_SELECTED;
1885 data->icld_UpdateMode = UPDATE_SINGLEICON;
1886 data->update_icon = node;
1887 MUI_Redraw(obj, MADF_DRAWUPDATE);
1889 data->icld_SelectionFirst = node;
1894 /* if not cliked on icon set lasso as active */
1895 if (!new_selected)
1897 data->icld_LassoActive = TRUE;
1899 data->icld_LassoRectangle.MinX = mx - data->view_rect.MinX + data->icld_ViewX;
1900 data->icld_LassoRectangle.MinY = my - data->view_rect.MinY + data->icld_ViewY;
1901 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
1902 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
1904 /* deselect old selection */
1905 DoMethod(obj, MUIM_IconList_UnselectAll);
1907 /* draw initial lasso */
1908 IconList_InvertLassoOutlines(obj, &data->icld_LassoRectangle);
1910 else
1912 data->icld_LassoActive = FALSE;
1914 /* remove last single selection if clicked on different file*/
1915 if (data->icld_SelectionLast && new_selected != data->icld_SelectionLast && selections < 2)
1917 data->icld_SelectionLast->ile_Flags &= ~ICONENTRY_FLAG_SELECTED;
1918 data->icld_UpdateMode = UPDATE_SINGLEICON;
1919 data->update_icon = data->icld_SelectionLast;
1920 MUI_Redraw(obj,MADF_DRAWUPDATE);
1924 data->icon_click.shift = !!(message->imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT));
1925 data->icon_click.entry = new_selected ? &new_selected->ile_IconListEntry : NULL;
1926 SET(obj, MUIA_IconList_Clicked, (IPTR)&data->icon_click);
1928 if (DoubleClick(data->last_secs, data->last_mics, message->imsg->Seconds, message->imsg->Micros) && data->icld_SelectionLast == new_selected)
1930 SET(obj, MUIA_IconList_DoubleClick, TRUE);
1931 data->icld_SelectionLast = NULL;
1933 else if (!data->mouse_pressed)
1935 data->icld_SelectionLast = new_selected;
1936 data->last_secs = message->imsg->Seconds;
1937 data->last_mics = message->imsg->Micros;
1939 /* After a double click you often open a new window
1940 * and since Zune doesn't not support the faking
1941 * of SELECTUP events only change the Events
1942 * if not doubleclicked */
1944 data->mouse_pressed |= LEFT_BUTTON;
1946 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
1948 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1949 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
1950 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
1954 data->click_x = mx;
1955 data->click_y = my;
1957 return MUI_EventHandlerRC_Eat;
1960 else if (message->imsg->Code == MIDDLEDOWN)
1962 if (!data->mouse_pressed)
1964 data->mouse_pressed |= MIDDLE_BUTTON;
1966 data->click_x = data->icld_ViewX + mx;
1967 data->click_y = data->icld_ViewY + my;
1969 if (!(data->ehn.ehn_Events & IDCMP_MOUSEMOVE))
1971 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
1972 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
1973 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
1977 else
1979 if (message->imsg->Code == SELECTUP)
1981 /* check if mose released on iconlist aswell */
1982 if (mx >= 0 && mx < _width(obj) && my >= 0 && my < _height(obj) && data->icld_LassoActive == FALSE)
1984 struct IconEntry *node = NULL;
1985 struct IconEntry *new_selected = NULL;
1987 data->icld_SelectionFirst = NULL;
1989 ForeachNode(&data->icld_IconList, node)
1991 if (node->ile_Flags & ICONENTRY_FLAG_VISIBLE)
1993 /* unselect all other nodes if mouse released on icon and lasso was not selected during mouse press */
1994 if ( ( (node->ile_Flags & ICONENTRY_FLAG_SELECTED) && data->icld_LassoActive == FALSE) &&
1995 ( mx < node->ile_IconX - data->icld_ViewX || mx > node->ile_IconX - data->icld_ViewX + node->ile_AreaWidth ||
1996 my < node->ile_IconY - data->icld_ViewY || my > node->ile_IconY - data->icld_ViewY + node->ile_AreaHeight ) )
1999 node->ile_Flags &= ~ICONENTRY_FLAG_SELECTED;
2000 data->icld_UpdateMode = UPDATE_SINGLEICON;
2001 data->update_icon = node;
2002 MUI_Redraw(obj,MADF_DRAWUPDATE);
2008 /* stop lasso selection/drawing now */
2009 if (data->icld_LassoActive == TRUE)
2011 /* make lasso disappear again */
2012 struct Rectangle old_lasso;
2013 GetAbsoluteLassoRect(data, &old_lasso);
2014 IconList_InvertLassoOutlines(obj, &old_lasso);
2016 data->icld_LassoActive = FALSE;
2019 data->mouse_pressed &= ~LEFT_BUTTON;
2022 if (message->imsg->Code == MIDDLEUP)
2024 data->mouse_pressed &= ~MIDDLE_BUTTON;
2027 if ((data->ehn.ehn_Events & IDCMP_MOUSEMOVE) && !data->mouse_pressed)
2029 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
2030 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
2031 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
2034 break;
2036 case IDCMP_MOUSEMOVE:
2038 if (data->mouse_pressed & LEFT_BUTTON)
2040 LONG move_x = mx;
2041 LONG move_y = my;
2043 /* check if clicked on icon, or update lasso coords if lasso activated */
2044 if (
2045 data->icld_SelectionFirst && data->icld_LassoActive == FALSE &&
2046 (abs(move_x - data->click_x) >= 2 || abs(move_y - data->click_y) >= 2)
2049 DoMethod(_win(obj),MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
2050 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
2051 DoMethod(_win(obj),MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
2053 data->mouse_pressed &= ~LEFT_BUTTON;
2055 data->touch_x = move_x + data->icld_ViewX - data->icld_SelectionFirst->ile_IconX;
2056 data->touch_y = move_y + data->icld_ViewY - data->icld_SelectionFirst->ile_IconY;
2057 DoMethod(obj,MUIM_DoDrag, data->touch_x, data->touch_y, 0);
2059 else if (data->icld_LassoActive == TRUE) /* if no icon selected start lasso */
2061 struct Rectangle new_lasso,
2062 old_lasso;
2063 struct IconEntry *node = NULL;
2064 struct IconEntry *new_selected = NULL;
2066 /* unmark old lasso area */
2067 GetAbsoluteLassoRect(data, &old_lasso);
2068 IconList_InvertLassoOutlines(obj, &old_lasso);
2070 /* if mouse leaves iconlist area during lasso mode, scroll view */
2071 if (mx < 0 || mx >= _mwidth(obj) || my < 0 || my >= _mheight(obj))
2073 WORD newleft = data->icld_ViewX;
2074 WORD newtop = data->icld_ViewY;
2076 if (mx >= _mwidth(obj)) newleft += 5;
2077 else if (mx < 0) newleft -= 5;
2078 if (my >= _mheight(obj)) newtop += 5;
2079 else if (my < 0) newtop -= 5;
2081 if (newleft + _mwidth(obj) > data->width) newleft = data->width - _mwidth(obj);
2082 if (newleft < 0) newleft = 0;
2084 if (newtop + _mheight(obj) > data->height) newtop = data->height - _mheight(obj);
2085 if (newtop < 0) newtop = 0;
2087 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
2089 SetAttrs(obj, MUIA_IconList_Left, newleft, MUIA_IconList_Top, newtop, TAG_DONE);
2093 /* update lasso coordinates */
2094 data->icld_LassoRectangle.MaxX = mx - data->view_rect.MinX + data->icld_ViewX;
2095 data->icld_LassoRectangle.MaxY = my - data->view_rect.MinY + data->icld_ViewY;
2097 /* get absolute lasso coordinates */
2098 GetAbsoluteLassoRect(data, &new_lasso);
2100 data->icld_SelectionFirst = NULL;
2102 ForeachNode(&data->icld_IconList, node)
2104 if (node->ile_Flags & ICONENTRY_FLAG_VISIBLE)
2106 /* check if clicked on icon */
2107 if (new_lasso.MaxX >= node->ile_IconX - data->icld_ViewX
2108 && new_lasso.MinX < node->ile_IconX - data->icld_ViewX + node->ile_AreaWidth &&
2109 new_lasso.MaxY >= node->ile_IconY - data->icld_ViewY
2110 && new_lasso.MinY < node->ile_IconY - data->icld_ViewY + node->ile_AreaHeight)
2112 new_selected = node;
2114 /* check if icon was already selected before */
2115 if (!(node->ile_Flags & ICONENTRY_FLAG_SELECTED))
2117 node->ile_Flags |= ICONENTRY_FLAG_SELECTED;
2118 data->icld_UpdateMode = UPDATE_SINGLEICON;
2119 data->update_icon = node;
2120 data->icld_SelectionLast = node; // <- I'm the latest addition to your flock! =)
2121 MUI_Redraw(obj, MADF_DRAWUPDATE);
2124 data->icld_SelectionFirst = node;
2126 else
2128 if (node->ile_Flags & ICONENTRY_FLAG_SELECTED) /* if not catched by lasso and selected before -> unselect */
2130 node->ile_Flags &= ~ICONENTRY_FLAG_SELECTED;
2131 data->icld_UpdateMode = UPDATE_SINGLEICON;
2132 data->update_icon = node;
2133 MUI_Redraw(obj, MADF_DRAWUPDATE);
2138 /* set lasso borders */
2139 IconList_InvertLassoOutlines(obj, &new_lasso);
2142 return MUI_EventHandlerRC_Eat;
2144 else if (data->mouse_pressed & MIDDLE_BUTTON)
2146 LONG newleft,
2147 newtop;
2149 newleft = data->click_x - mx;
2150 newtop = data->click_y - my;
2152 if (newleft + _mwidth(obj) > data->width) newleft = data->width - _mwidth(obj);
2153 if (newleft < 0) newleft = 0;
2155 if (newtop + _mheight(obj) > data->height) newtop = data->height - _mheight(obj);
2156 if (newtop < 0) newtop = 0;
2158 if ((newleft != data->icld_ViewX) || (newtop != data->icld_ViewY))
2160 SetAttrs(obj, MUIA_IconList_Left, newleft,
2161 MUIA_IconList_Top, newtop,
2162 TAG_DONE);
2165 return MUI_EventHandlerRC_Eat;
2168 break;
2172 return 0;
2175 /**************************************************************************
2176 MUIM_IconList_NextSelected
2177 **************************************************************************/
2178 IPTR IconList__MUIM_IconList_NextSelected(struct IClass *CLASS, Object *obj, struct MUIP_IconList_NextSelected *message)
2180 struct MUI_IconData *data = INST_DATA(CLASS, obj);
2181 struct IconEntry *node = NULL;
2182 struct IconList_Entry *ent = NULL;
2184 if (!message->entry) return (IPTR)NULL;
2185 ent = *message->entry;
2187 if (((IPTR)ent) == MUIV_IconList_NextSelected_Start)
2189 if (!(node = data->icld_SelectionLast))
2191 D(bug("[IconList] IconList__MUIM_IconList_NextSelected: No selected entries!!!\n"));
2192 *message->entry = (struct IconList_Entry*)MUIV_IconList_NextSelected_End;
2194 else
2196 /* get the first selected entry in list */
2197 node = List_First(&data->icld_IconList);
2198 while (!(node->ile_Flags & ICONENTRY_FLAG_SELECTED))
2200 node = Node_Next(node);
2203 *message->entry = &node->ile_IconListEntry;
2205 return 0;
2208 node = List_First(&data->icld_IconList); /* not really necessary but it avoids compiler warnings */
2210 node = (struct IconEntry*)(((char*)ent) - ((char*)(&node->ile_IconListEntry) - (char*)node));
2211 node = Node_Next(node);
2213 while (node)
2215 if (node->ile_Flags & ICONENTRY_FLAG_SELECTED)
2217 *message->entry = &node->ile_IconListEntry;
2218 return 0;
2220 node = Node_Next(node);
2223 *message->entry = (struct IconList_Entry*)MUIV_IconList_NextSelected_End;
2225 return (IPTR)NULL;
2228 /**************************************************************************
2229 MUIM_CreateDragImage
2230 **************************************************************************/
2231 IPTR IconList__MUIM_CreateDragImage(struct IClass *CLASS, Object *obj, struct MUIP_CreateDragImage *message)
2233 struct MUI_IconData *data = INST_DATA(CLASS, obj);
2234 struct MUI_DragImage *img = NULL;
2236 if (!data->icld_SelectionFirst) DoSuperMethodA(CLASS, obj, (Msg)message);
2238 if ((img = (struct MUI_DragImage *)AllocVec(sizeof(struct MUIP_CreateDragImage), MEMF_CLEAR)))
2240 struct IconEntry *node = NULL;
2241 LONG depth = GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH);
2243 node = data->icld_SelectionFirst;
2245 img->width = node->ile_IconWidth;
2246 img->height = node->ile_IconHeight;
2248 if ((img->bm = AllocBitMap(img->width, img->height, depth, BMF_MINPLANES|BMF_CLEAR, _screen(obj)->RastPort.BitMap)))
2250 struct RastPort temprp;
2251 InitRastPort(&temprp);
2252 temprp.BitMap = img->bm;
2254 #ifndef __AROS__
2255 DrawIconState(&temprp, node->ile_DiskObj, NULL, 0, 0, (node->ile_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL, ICONDRAWA_EraseBackground, TRUE, TAG_DONE);
2256 #else
2257 DrawIconStateA(&temprp, node->ile_DiskObj, NULL, 0, 0, (node->ile_Flags & ICONENTRY_FLAG_SELECTED) ? IDS_SELECTED : IDS_NORMAL, NULL);
2258 #endif
2259 DeinitRastPort(&temprp);
2262 img->touchx = message->touchx;
2263 img->touchy = message->touchy;
2264 img->flags = 0;
2266 return (ULONG)img;
2269 /**************************************************************************
2270 MUIM_DeleteDragImage
2271 **************************************************************************/
2272 IPTR IconList__MUIM_DeleteDragImage(struct IClass *CLASS, Object *obj, struct MUIP_DeleteDragImage *message)
2274 struct MUI_IconData *data = INST_DATA(CLASS, obj);
2276 if (!data->icld_SelectionFirst) return DoSuperMethodA(CLASS,obj,(Msg)message);
2278 if (message->di)
2280 if (message->di->bm)
2281 FreeBitMap(message->di->bm);
2282 FreeVec(message->di);
2284 return (IPTR)NULL;
2287 /**************************************************************************
2288 MUIM_DragQuery
2289 **************************************************************************/
2290 IPTR IconList__MUIM_DragQuery(struct IClass *CLASS, Object *obj, struct MUIP_DragQuery *message)
2292 if (message->obj == obj) return MUIV_DragQuery_Accept;
2293 else
2295 BOOL is_iconlist = FALSE;
2296 struct IClass *msg_cl = OCLASS(message->obj);
2298 while (msg_cl)
2300 if (msg_cl == CLASS)
2302 is_iconlist = TRUE;
2303 break;
2305 msg_cl = msg_cl->cl_Super;
2307 if (is_iconlist) return MUIV_DragQuery_Accept;
2310 return MUIV_DragQuery_Refuse;
2313 /**************************************************************************
2314 MUIM_DragDrop
2315 **************************************************************************/
2316 IPTR IconList__MUIM_DragDrop(struct IClass *CLASS, Object *obj, struct MUIP_DragDrop *message)
2318 struct MUI_IconData *data = INST_DATA(CLASS, obj);
2320 /* check if dropped on same iconlist object */
2321 if (message->obj == obj)
2323 struct IconEntry *icon = data->icld_SelectionFirst;
2325 if (icon)
2327 struct Region *region = NULL;
2328 struct Rectangle rect_old,
2329 rect_new;
2330 APTR clip = NULL;
2332 /* icon moved, dropped in the same window */
2333 SET(obj, MUIA_IconList_IconsMoved, (IPTR) &(data->icld_SelectionFirst->ile_IconListEntry)); /* Now notify */
2334 D(bug("[IconList] IconList__MUIM_DragDrop: move entry: %s dropped in same window\n", data->icld_SelectionFirst->ile_IconListEntry.filename); )
2336 IconList_GetIconRectangle(obj, data, icon, &rect_old);
2338 rect_old.MinX += _mleft(obj) - data->icld_ViewX + icon->ile_IconX;
2339 rect_old.MaxX += _mleft(obj) - data->icld_ViewX + icon->ile_IconX;
2340 rect_old.MinY += _mtop(obj) - data->icld_ViewY + icon->ile_IconY;
2341 rect_old.MaxY += _mtop(obj) - data->icld_ViewY + icon->ile_IconY;
2343 icon->ile_IconX = message->x - _mleft(obj) + data->icld_ViewX - data->touch_x;
2344 icon->ile_IconY = message->y - _mtop(obj) + data->icld_ViewY - data->touch_y;
2346 IconList_RethinkDimensions(obj, data, data->icld_SelectionFirst);
2348 IconList_GetIconRectangle(obj, data, data->icld_SelectionFirst, &rect_new);
2350 rect_new.MinX += _mleft(obj) - data->icld_ViewX + icon->ile_IconX;
2351 rect_new.MaxX += _mleft(obj) - data->icld_ViewX + icon->ile_IconX;
2352 rect_new.MaxX += _mleft(obj) - data->icld_ViewX + icon->ile_IconX;
2353 rect_new.MinY += _mtop(obj) - data->icld_ViewY + icon->ile_IconY;
2354 rect_new.MaxY += _mtop(obj) - data->icld_ViewY + icon->ile_IconY;
2356 region = NewRegion();
2357 if (region)
2359 OrRectRegion(region, &rect_old);
2360 OrRectRegion(region, &rect_new);
2361 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
2364 MUI_Redraw(obj,MADF_DRAWOBJECT);
2366 if (region)
2368 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
2372 else
2374 struct IconEntry *icon = NULL;
2375 struct IconList_Entry *entry = (APTR) MUIV_IconList_NextSelected_Start;
2377 /* get selected entries from SOURCE iconlist */
2378 DoMethod(message->obj, MUIM_IconList_NextSelected, (IPTR) &entry);
2380 /* check if dropped on an icon on the iconlist area */
2381 if (entry)
2383 /* check if dropped on a drawer */
2384 struct IconEntry *node = NULL;
2385 struct IconEntry *drop_target_node = NULL;
2387 /* go through list and check if dropped on icon */
2388 ForeachNode(&data->icld_IconList, node)
2390 if (message->x >= node->ile_IconX - data->icld_ViewX &&
2391 message->x < node->ile_IconX - data->icld_ViewX + node->ile_AreaWidth &&
2392 message->y >= node->ile_IconY - data->icld_ViewY + _mtop(obj) &&
2393 message->y < node->ile_IconY - data->icld_ViewY + node->ile_AreaHeight + _mtop(obj) && !drop_target_node)
2395 drop_target_node = node;
2399 /* get path to destination directory */
2400 STRPTR directory_path = NULL;
2401 GET(obj, MUIA_IconDrawerList_Drawer, &directory_path);
2403 /* check if dropped on a root drive -
2404 last condition is a hack, based upon another hack (adding ":Disk" to rootdrive name)
2405 since ST_ROOT seems not to be set properly right now (?) */
2406 if (drop_target_node && ((drop_target_node->ile_IconListEntry.type == ST_ROOT)
2407 || (!strcmp(drop_target_node->ile_IconListEntry.filename + strlen(drop_target_node->ile_IconListEntry.filename) - 5, ":Disk"))))
2409 int tmplen = 0;
2411 /* avoid copying "Disk" (hack anyway?!) from root drive name, eg. "Ram Disk:Disk"*/
2412 tmplen = strlen(drop_target_node->ile_IconListEntry.filename) - 4;
2414 /* copy path of dir icon dropped on */
2415 strncpy(data->drop_entry.destination_string, drop_target_node->ile_IconListEntry.filename, tmplen);
2417 /* mark the drive the icon was dropped on*/
2418 drop_target_node->ile_Flags |= ICONENTRY_FLAG_SELECTED;
2419 data->icld_UpdateMode = UPDATE_SINGLEICON;
2420 data->update_icon = drop_target_node;
2421 MUI_Redraw(obj,MADF_DRAWUPDATE);
2423 D(bug("[IconList] IconList__MUIM_DragDrop: drop entry: %s dropped on disk icon %s\n", entry->filename, drop_target_node->ile_IconListEntry.filename); )
2425 /* check if dropped on a drawer icon in iconlist */
2426 else if (drop_target_node && (drop_target_node->ile_IconListEntry.type == ST_USERDIR))
2428 /* copy path of dir icon dropped on */
2429 strcpy(data->drop_entry.destination_string, drop_target_node->ile_IconListEntry.filename);
2431 /* mark the directory the icon was dropped on*/
2432 drop_target_node->ile_Flags |= ICONENTRY_FLAG_SELECTED;
2433 data->icld_UpdateMode = UPDATE_SINGLEICON;
2434 data->update_icon = drop_target_node;
2435 MUI_Redraw(obj,MADF_DRAWUPDATE);
2437 D(bug("[IconList] IconList__MUIM_DragDrop: drop entry: %s dropped on dir %s icon in window %s\n", entry->filename, drop_target_node->ile_IconListEntry.filename, directory_path); )
2439 else
2441 /* not dropped on icon -> get path of DESTINATION iconlist */
2442 D(bug("[IconList] IconList__MUIM_DragDrop: drop entry: %s dropped in window %s\n", entry->filename, directory_path); )
2443 /* copy path */
2444 strcpy(data->drop_entry.destination_string, directory_path);
2447 /* copy relevant data to drop entry */
2448 data->drop_entry.source_iconlistobj = (IPTR)message->obj;
2449 data->drop_entry.destination_iconlistobj = (IPTR)obj;
2451 /* return drop entry */
2452 SET(obj, MUIA_IconList_IconsDropped, (IPTR)&data->drop_entry); /* Now notify */
2454 else
2456 /* no drop entry */
2457 SET(obj, MUIA_IconList_IconsDropped, (IPTR)NULL); /* Now notify */
2461 return DoSuperMethodA(CLASS, obj, (Msg)message);
2464 /**************************************************************************
2465 MUIM_UnselectAll
2466 **************************************************************************/
2467 IPTR IconList__MUIM_IconList_UnselectAll(struct IClass *CLASS, Object *obj, Msg message)
2469 struct MUI_IconData *data = INST_DATA(CLASS, obj);
2470 struct IconEntry *node = NULL;
2472 ForeachNode(&data->icld_IconList, node)
2474 if (node->ile_Flags & ICONENTRY_FLAG_SELECTED)
2476 node->ile_Flags &= ~ICONENTRY_FLAG_SELECTED;
2477 data->icld_UpdateMode = UPDATE_SINGLEICON;
2478 data->update_icon = node;
2479 MUI_Redraw(obj, MADF_DRAWUPDATE);
2482 data->icld_SelectionFirst = NULL;
2483 data->icld_SelectionLast = NULL;
2484 return 1;
2487 /**************************************************************************
2488 MUIM_SelectAll
2489 **************************************************************************/
2490 IPTR IconList__MUIM_IconList_SelectAll(struct IClass *CLASS, Object *obj, Msg message)
2492 struct MUI_IconData *data = INST_DATA(CLASS, obj);
2493 struct IconEntry *node = NULL;
2495 node = List_First(&data->icld_IconList);
2496 data->icld_SelectionFirst = node;
2497 while (node)
2499 if (!(node->ile_Flags & ICONENTRY_FLAG_SELECTED))
2501 node->ile_Flags |= ICONENTRY_FLAG_SELECTED;
2502 data->icld_UpdateMode = UPDATE_SINGLEICON;
2503 data->update_icon = node;
2504 data->icld_SelectionLast = node;
2505 MUI_Redraw(obj, MADF_DRAWUPDATE);
2507 node = Node_Next(node);
2510 return 1;
2513 struct MUI_IconDrawerData
2515 char *drawer;
2518 /**************************************************************************
2519 Read icons in
2520 **************************************************************************/
2521 static int IconDrawerList__ParseContents(struct IClass *CLASS, Object *obj)
2523 struct MUI_IconDrawerData *data = INST_DATA(CLASS, obj);
2524 BPTR lock = NULL, tmplock = NULL;
2525 char filename[256];
2526 char namebuffer[512];
2527 ULONG list_DisplayFlags = 0;
2529 if (!data->drawer) return 1;
2531 lock = Lock(data->drawer, SHARED_LOCK);
2533 if (lock)
2535 struct FileInfoBlock *fib = AllocDosObject(DOS_FIB, NULL);
2536 if (fib)
2538 if (Examine(lock, fib))
2540 GET(obj, MUIA_IconList_DisplayFlags, &list_DisplayFlags);
2541 D(bug("[IconList] IconDrawerList__ParseContents: DisplayFlags = %x\n", list_DisplayFlags));
2543 while(ExNext(lock, fib))
2545 int len = strlen(fib->fib_FileName);
2546 memset(namebuffer, 0, 512);
2547 strcpy(filename, fib->fib_FileName);
2549 D(bug("[IconList] IconDrawerList__ParseContents: '%s', len = %d\n", filename, len));
2551 if (len >= 5)
2553 if (!Stricmp(&filename[len-5],".info"))
2555 /* Its a .info file .. skip "disk.info" and just ".info" files*/
2556 if ((len == 5) || (!Stricmp(filename,"Disk")))
2558 D(bug("[IconList] IconDrawerList__ParseContents: Skiping file named disk.info or just .info ('%s')\n", filename));
2559 continue;
2562 strcpy(namebuffer, data->drawer);
2563 memset((filename + len - 5), 0, 1); //Remove the .info section
2564 AddPart(namebuffer, filename, sizeof(namebuffer));
2565 D(bug("[IconList] IconDrawerList__ParseContents: Checking for .info files real file '%s'\n", namebuffer));
2567 if (tmplock = Lock(namebuffer, SHARED_LOCK))
2569 /* We have a real file so skip it for now and let it be found seperately */
2570 D(bug("[IconList] IconDrawerList__ParseContents: File found .. skipping\n"));
2571 UnLock(tmplock);
2572 continue;
2577 D(bug("[IconList] IconDrawerList__ParseContents: Registering file '%s'\n", filename));
2578 strcpy(namebuffer, data->drawer);
2579 AddPart(namebuffer, filename, sizeof(namebuffer));
2581 struct IconEntry *this_Icon = NULL;
2583 if (this_Icon = DoMethod(obj, MUIM_IconList_CreateEntry, (IPTR)namebuffer, (IPTR)filename, (IPTR)fib, (IPTR)NULL))
2585 sprintf(namebuffer + strlen(namebuffer), ".info");
2586 if (tmplock = Lock(namebuffer, SHARED_LOCK))
2588 D(bug("[IconList] IconDrawerList__ParseContents: File has a .info file .. updating info\n"));
2589 UnLock(tmplock);
2590 if (!(this_Icon->ile_Flags & ICONENTRY_FLAG_HASICON))
2591 this_Icon->ile_Flags |= ICONENTRY_FLAG_HASICON;
2594 if (list_DisplayFlags & ICONLIST_DISP_SHOWINFO)
2596 if ((this_Icon->ile_Flags & ICONENTRY_FLAG_HASICON) && !(this_Icon->ile_Flags & ICONENTRY_FLAG_VISIBLE))
2597 this_Icon->ile_Flags |= ICONENTRY_FLAG_VISIBLE;
2599 else if (!(this_Icon->ile_Flags & ICONENTRY_FLAG_VISIBLE))
2601 this_Icon->ile_Flags |= ICONENTRY_FLAG_VISIBLE;
2603 this_Icon->ile_Node.ln_Pri = 0;
2605 else
2607 D(bug("[IconList] IconDrawerList__ParseContents: Failed to Register file!!!\n"));
2612 FreeDosObject(DOS_FIB, fib);
2615 UnLock(lock);
2618 return 1;
2622 static int OLDReadIcons(struct IClass *CLASS, Object *obj)
2624 struct MUI_IconDrawerData *data = INST_DATA(CLASS, obj);
2625 BPTR lock;
2627 struct ExAllControl *eac;
2628 struct ExAllData *entry;
2629 void *ead;
2630 LONG more;
2631 BPTR olddir;
2632 //char pattern[40];
2633 char filename[256];
2635 if (!data->drawer) return 1;
2636 lock = Lock(data->drawer,ACCESS_READ);
2637 if (!lock) return 0;
2639 eac = (struct ExAllControl*)AllocDosObject(DOS_EXALLCONTROL,NULL);
2640 if (!eac)
2642 UnLock(lock);
2643 return 0;
2646 ead = AllocVec(1024,0);
2647 if (!ead)
2649 FreeDosObject(DOS_EXALLCONTROL,eac);
2650 UnLock(lock);
2651 return 0;
2654 *//*
2655 ParsePatternNoCase("#?.info",pattern,sizeof(pattern));
2656 eac->eac_MatchString = pattern;
2657 *//*
2658 #ifdef __AROS__
2659 #warning AROS ExAll() doesnt support eac_MatchString
2660 #endif
2661 eac->eac_MatchString = NULL;
2662 eac->eac_LastKey = 0;
2664 olddir = CurrentDir(lock);
2668 more = ExAll(lock,ead,1024,ED_TYPE,eac);
2669 if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) break;
2670 if (eac->eac_Entries == 0) continue;
2672 entry = (struct ExAllData*)ead;
2675 int len;
2677 strcpy(filename,entry->ile_ed_Name);
2679 *//*
2680 // if we only display icons
2682 filename[strlen(filename)-5]=0;
2683 *//*
2684 len = strlen(filename);
2685 if (len >= 5)
2687 *//* reject all .info files, so we have a Show All mode *//*
2688 if (!Stricmp(&filename[len-5],".info"))
2689 continue;
2692 if (Stricmp(filename,"Disk")) *//* skip disk.info *//*
2694 char buf[512];
2695 strcpy(buf,data->drawer);
2696 AddPart(buf,filename,sizeof(buf));
2698 if (!(DoMethod(obj,MUIM_IconList_CreateEntry,(IPTR)buf,(IPTR)filename,entry->ile_ed_Type,NULL *//* udata *//*)))
2702 } while ((entry = entry->ile_ed_Next));
2703 } while (more);
2705 CurrentDir(olddir);
2707 FreeVec(ead);
2708 FreeDosObject(DOS_EXALLCONTROL,eac);
2709 UnLock(lock);
2710 return 1;
2714 /**************************************************************************
2715 MUIM_Sort - sortsort
2716 **************************************************************************/
2717 IPTR IconList__MUIM_IconList_Sort(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Sort *message)
2719 struct MUI_IconData *data = INST_DATA(CLASS, obj);
2720 struct IconEntry *entry = NULL,
2721 *icon1 = NULL,
2722 *icon2 = NULL;
2723 struct List list_VisibleIcons,
2724 list_SortedIcons,
2725 list_HiddenIcons;
2727 BOOL sortme;
2728 int i, visible_count = 0;
2730 NewList((struct List*)&list_VisibleIcons);
2731 NewList((struct List*)&list_SortedIcons);
2732 NewList((struct List*)&list_HiddenIcons);
2734 /*move list int out local list struct*/
2735 // entry = List_First(&data->icld_IconList);
2736 while ((entry = (struct IconEntry *)RemTail((struct List*)&data->icld_IconList)))
2738 if (!(entry->ile_Flags & ICONENTRY_FLAG_HASICON))
2741 if (data->icld_DisplayFlags & ICONLIST_DISP_SHOWINFO)
2743 if (entry->ile_Flags & ICONENTRY_FLAG_VISIBLE)
2744 entry->ile_Flags &= ~ICONENTRY_FLAG_VISIBLE;
2746 else if (!(entry->ile_Flags & ICONENTRY_FLAG_VISIBLE))
2747 entry->ile_Flags |= ICONENTRY_FLAG_VISIBLE;
2749 else
2751 if (!(entry->ile_Flags & ICONENTRY_FLAG_VISIBLE))
2752 entry->ile_Flags |= ICONENTRY_FLAG_VISIBLE;
2755 /* Now we have fixed visibility lets dump them into the correct list for sorting */
2756 if (entry->ile_Flags & ICONENTRY_FLAG_VISIBLE)
2758 AddHead((struct List*)&list_VisibleIcons, (struct Node *)entry);
2759 visible_count++;
2761 else AddHead((struct List*)&list_HiddenIcons, (struct Node *)entry);
2764 /*now copy each one back to the main list, sorting as we go*/
2765 // entry = List_First(&list_VisibleIcons);
2766 while ((entry = (struct IconEntry *)RemTail((struct List*)&list_VisibleIcons)))
2768 icon1 = List_First(&list_SortedIcons);
2769 icon2 = NULL;
2770 sortme = FALSE;
2772 if (visible_count > 1)
2774 //D(bug(" - %s %s %s %i\n",entry->ile_IconListEntry.label,entry->ile_TxtBuf_DATE,entry->ile_TxtBuf_TIME,entry->ile_FileInfoBlock.fib_Size));
2776 while (icon1)
2778 if(data->icld_SortFlags & ICONLIST_SORT_DRAWERS_MIXED)
2780 /*drawers mixed*/
2782 sortme = TRUE;
2784 else
2786 /*drawers first*/
2788 if ((icon1->ile_IconListEntry.type == WBDRAWER) && (entry->ile_IconListEntry.type == WBDRAWER))
2790 sortme = TRUE;
2792 else
2794 if ((icon1->ile_IconListEntry.type != WBDRAWER) && (entry->ile_IconListEntry.type != WBDRAWER))
2795 sortme = TRUE;
2796 else
2798 /* we are the first drawer to arrive or we need to insert ourselves
2799 due to being sorted to the end of the drawers*/
2801 if ((!icon2 || icon2->ile_IconListEntry.type == WBDRAWER) &&
2802 (entry->ile_IconListEntry.type == WBDRAWER) &&
2803 (icon1->ile_IconListEntry.type != WBDRAWER))
2805 //D(bug("force %s\n",entry->ile_IconListEntry.label));
2806 break;
2812 if (sortme)
2814 i = 0;
2816 if( (data->icld_SortFlags & ICONLIST_SORT_BY_DATE) && !(data->icld_SortFlags & ICONLIST_SORT_BY_SIZE) )
2818 /* Sort by Date */
2819 i = CompareDates((const struct DateStamp *)&entry->ile_FileInfoBlock.fib_Date,(const struct DateStamp *)&icon1->ile_FileInfoBlock.fib_Date);
2820 //D(bug(" - %i\n",i));
2822 else
2824 if( (data->icld_SortFlags & ICONLIST_SORT_BY_SIZE) && !(data->icld_SortFlags & ICONLIST_SORT_BY_DATE) )
2826 /* Sort by Size .. */
2827 i = entry->ile_FileInfoBlock.fib_Size - icon1->ile_FileInfoBlock.fib_Size;
2828 //D(bug(" - %i\n",i));
2830 else if( data->icld_SortFlags & (ICONLIST_SORT_BY_DATE | ICONLIST_SORT_BY_SIZE) )
2832 /* Sort by Type .. */
2834 else
2836 /* Sort by Name .. */
2837 i = Stricmp(entry->ile_IconListEntry.label, icon1->ile_IconListEntry.label);
2841 if (!(data->icld_SortFlags & ICONLIST_SORT_REVERSE) && (i < 0))
2842 break;
2844 if ((data->icld_SortFlags & ICONLIST_SORT_REVERSE) && (i > 0))
2845 break;
2847 icon2 = icon1;
2848 icon1 = Node_Next( icon1 );
2851 Insert((struct List*)&list_SortedIcons, (struct Node *)entry, (struct Node *)icon2);
2854 /* Quickly resort based on node priorities .. */
2855 while ((entry = (struct IconEntry *)RemHead((struct List*)&list_SortedIcons)))
2857 Enqueue((struct List*)&data->icld_IconList, (struct Node *)entry);
2860 DoMethod(obj, MUIM_IconList_PositionIcons);
2861 MUI_Redraw(obj, MADF_DRAWOBJECT);
2863 #warning "TODO: leave hidden icons on a seperate list to speed up normal list parsing"
2864 // entry = List_First(&list_HiddenIcons);
2865 while ((entry = (struct IconEntry *)RemTail((struct List*)&list_HiddenIcons)))
2867 AddTail((struct List*)&data->icld_IconList, (struct Node *)entry);
2870 return 1;
2873 /**************************************************************************
2874 MUIM_DragReport. Since MUI doesn't change the drop object if the dragged
2875 object is moved above another window (while still in the bounds of the
2876 orginal drop object) we must do it here manually to be compatible with
2877 MUI. Maybe Zune should fix this bug somewhen.
2878 **************************************************************************/
2879 IPTR IconList__MUIM_DragReport(struct IClass *CLASS, Object *obj, struct MUIP_DragReport *message)
2881 struct Window *wnd = _window(obj);
2882 struct Layer *l = NULL;
2884 l = WhichLayer(&wnd->WScreen->LayerInfo, wnd->LeftEdge + message->x, wnd->TopEdge + message->y);
2886 if (l != wnd->WLayer) return MUIV_DragReport_Abort;
2888 return MUIV_DragReport_Continue;
2891 /**************************************************************************
2892 MUIM_IconList_UnknownDropDestination
2893 **************************************************************************/
2895 IPTR IconList__MUIM_UnknownDropDestination(struct IClass *CLASS, Object *obj, struct MUIP_UnknownDropDestination *message)
2897 D(bug("[IconList] IconList__MUIM_UnknownDropDestination: icons dropped on custom window \n"));
2899 SET(obj, MUIA_IconList_AppWindowDrop, (IPTR)message); /* Now notify */
2901 return 0;
2904 /*************************************************************************/
2906 BOOPSI_DISPATCHER(IPTR,IconList_Dispatcher, CLASS, obj, message)
2908 switch (message->MethodID)
2910 case OM_NEW: return IconList__OM_NEW(CLASS, obj, (struct opSet *)message);
2911 case OM_DISPOSE: return IconList__OM_DISPOSE(CLASS, obj, message);
2912 case OM_SET: return IconList__OM_SET(CLASS, obj, (struct opSet *)message);
2913 case OM_GET: return IconList__OM_GET(CLASS, obj, (struct opGet *)message);
2915 case MUIM_Setup: return IconList__MUIM_Setup(CLASS, obj, (struct MUIP_Setup *)message);
2917 case MUIM_Show: return IconList__MUIM_Show(CLASS,obj, (struct MUIP_Show *)message);
2918 case MUIM_Cleanup: return IconList__MUIM_Cleanup(CLASS, obj, (struct MUIP_Cleanup *)message);
2919 case MUIM_AskMinMax: return IconList__MUIM_AskMinMax(CLASS, obj, (struct MUIP_AskMinMax *)message);
2920 case MUIM_Draw: return IconList__MUIM_Draw(CLASS, obj, (struct MUIP_Draw *)message);
2921 case MUIM_Layout: return IconList__MUIM_Layout(CLASS, obj, (struct MUIP_Layout *)message);
2922 case MUIM_HandleEvent: return IconList__MUIM_HandleEvent(CLASS, obj, (struct MUIP_HandleEvent *)message);
2923 case MUIM_CreateDragImage: return IconList__MUIM_CreateDragImage(CLASS, obj, (APTR)message);
2924 case MUIM_DeleteDragImage: return IconList__MUIM_DeleteDragImage(CLASS, obj, (APTR)message);
2925 case MUIM_DragQuery: return IconList__MUIM_DragQuery(CLASS, obj, (APTR)message);
2926 case MUIM_DragReport: return IconList__MUIM_DragReport(CLASS, obj, (APTR)message);
2927 case MUIM_DragDrop: return IconList__MUIM_DragDrop(CLASS, obj, (APTR)message);
2928 case MUIM_UnknownDropDestination: return IconList__MUIM_UnknownDropDestination(CLASS, obj, (APTR)message);
2929 case MUIM_IconList_Update: return IconList__MUIM_IconList_Update(CLASS, obj, (APTR)message);
2930 case MUIM_IconList_Clear: return IconList__MUIM_IconList_Clear(CLASS, obj, (APTR)message);
2931 case MUIM_IconList_CreateEntry: return IconList__MUIM_IconList_CreateEntry(CLASS, obj, (APTR)message);
2932 case MUIM_IconList_DestroyEntry: return IconList__MUIM_IconList_DestroyEntry(CLASS, obj, (APTR)message);
2933 case MUIM_IconList_NextSelected: return IconList__MUIM_IconList_NextSelected(CLASS, obj, (APTR)message);
2934 case MUIM_IconList_UnselectAll: return IconList__MUIM_IconList_UnselectAll(CLASS, obj, (APTR)message);
2935 case MUIM_IconList_Sort: return IconList__MUIM_IconList_Sort(CLASS, obj, (APTR)message);
2936 case MUIM_IconList_PositionIcons: return IconList__MUIM_IconList_PositionIcons(CLASS, obj, (APTR)message);
2937 case MUIM_IconList_SelectAll: return IconList__MUIM_IconList_SelectAll(CLASS, obj, (APTR)message);
2940 return DoSuperMethodA(CLASS, obj, message);
2942 BOOPSI_DISPATCHER_END
2945 /**************************************************************************
2946 OM_NEW
2947 **************************************************************************/
2948 IPTR IconDrawerList__OM_NEW(struct IClass *CLASS, Object *obj, struct opSet *message)
2950 struct MUI_IconDrawerData *data = NULL;
2951 struct TagItem *tag = NULL,
2952 *tags = NULL;
2954 obj = (Object *)DoSuperNewTags(CLASS, obj, NULL,
2955 TAG_MORE, (IPTR) message->ops_AttrList);
2957 if (!obj) return FALSE;
2959 data = INST_DATA(CLASS, obj);
2961 /* parse initial taglist */
2962 for (tags = message->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
2964 switch (tag->ti_Tag)
2966 case MUIA_IconDrawerList_Drawer:
2967 data->drawer = StrDup((char*)tag->ti_Data);
2968 break;
2972 return (IPTR)obj;
2975 /**************************************************************************
2976 OM_DISPOSE
2977 **************************************************************************/
2978 IPTR IconDrawerList__OM_DISPOSE(struct IClass *CLASS, Object *obj, Msg message)
2980 struct MUI_IconDrawerData *data = INST_DATA(CLASS, obj);
2982 if (data->drawer) FreeVec(data->drawer);
2984 return DoSuperMethodA(CLASS, obj, message);
2987 /**************************************************************************
2988 OM_SET
2989 **************************************************************************/
2990 IPTR IconDrawerList__OM_SET(struct IClass *CLASS, Object *obj, struct opSet *message)
2992 struct MUI_IconDrawerData *data = INST_DATA(CLASS, obj);
2993 struct TagItem *tag = NULL,
2994 *tags = NULL;
2996 /* parse initial taglist */
2997 for (tags = message->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
2999 switch (tag->ti_Tag)
3001 case MUIA_IconDrawerList_Drawer:
3002 if (data->drawer) FreeVec(data->drawer);
3004 data->drawer = StrDup((char*)tag->ti_Data);
3005 DoMethod(obj, MUIM_IconList_Update);
3007 break;
3011 return DoSuperMethodA(CLASS, obj, (Msg)message);
3014 /**************************************************************************
3015 OM_GET
3016 **************************************************************************/
3017 IPTR IconDrawerList__OM_GET(struct IClass *CLASS, Object *obj, struct opGet *message)
3019 /* small macro to simplify return value storage */
3020 #define STORE *(message->opg_Storage)
3021 struct MUI_IconDrawerData *data = INST_DATA(CLASS, obj);
3023 switch (message->opg_AttrID)
3025 case MUIA_IconDrawerList_Drawer: STORE = (unsigned long)data->drawer; return 1;
3028 if (DoSuperMethodA(CLASS, obj, (Msg) message)) return 1;
3029 return 0;
3030 #undef STORE
3033 /**************************************************************************
3034 MUIM_IconList_Update
3035 **************************************************************************/
3036 IPTR IconDrawerList__MUIM_Update(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Update *message)
3038 //struct MUI_IconDrawerData *data = INST_DATA(CLASS, obj);
3039 //struct IconEntry *node;
3040 // struct MUI_IconData *data = INST_DATA(CLASS, obj);
3041 DoMethod(obj, MUIM_IconList_Clear);
3043 /* If not in setup do nothing */
3044 if (!(_flags(obj) & MADF_SETUP)) return 1;
3046 IconDrawerList__ParseContents(CLASS, obj);
3048 /*_Sort takes care of icon placement and redrawing for us*/
3049 DoMethod(obj, MUIM_IconList_Sort);
3051 return 1;
3055 BOOPSI_DISPATCHER(IPTR, IconDrawerList_Dispatcher, CLASS, obj, message)
3057 switch (message->MethodID)
3059 case OM_NEW: return IconDrawerList__OM_NEW(CLASS, obj, (struct opSet *)message);
3060 case OM_DISPOSE: return IconDrawerList__OM_DISPOSE(CLASS, obj, message);
3061 case OM_SET: return IconDrawerList__OM_SET(CLASS, obj, (struct opSet *)message);
3062 case OM_GET: return IconDrawerList__OM_GET(CLASS, obj, (struct opGet *)message);
3063 case MUIM_IconList_Update: return IconDrawerList__MUIM_Update(CLASS, obj, (APTR)message);
3065 return DoSuperMethodA(CLASS, obj, message);
3067 BOOPSI_DISPATCHER_END
3069 /* sba: taken from SimpleFind3 */
3071 struct NewDosList
3073 struct List list;
3074 APTR pool;
3077 struct NewDosNode
3079 struct Node node;
3080 STRPTR name;
3081 STRPTR device;
3082 struct MsgPort *port;
3085 static struct NewDosList *IconVolumeList__CreateDOSList(void)
3087 APTR pool = CreatePool(MEMF_PUBLIC,4096,4096);
3088 if (pool)
3090 struct NewDosList *ndl = (struct NewDosList*)AllocPooled(pool, sizeof(struct NewDosList));
3091 if (ndl)
3093 struct DosList *dl = NULL;
3095 NewList((struct List*)ndl);
3096 ndl->pool = pool;
3098 dl = LockDosList(LDF_VOLUMES|LDF_READ);
3099 while(( dl = NextDosEntry(dl, LDF_VOLUMES)))
3101 STRPTR name;
3102 #ifndef __AROS__
3103 UBYTE *dosname = (UBYTE*)BADDR(dl->dol_Name);
3104 LONG len = dosname[0];
3105 dosname++;
3106 #else
3107 UBYTE *dosname = dl->dol_DevName;
3108 LONG len = strlen(dosname);
3109 #endif
3111 if ((name = (STRPTR)AllocPooled(pool, len + 1)))
3113 struct NewDosNode *ndn = NULL;
3115 name[len] = 0;
3116 strncpy(name, dosname, len);
3118 if ((ndn = (struct NewDosNode*)AllocPooled(pool, sizeof(*ndn))))
3120 D(bug("[IconList]: IconVolumeList__CreateDOSList: adding node for '%s'\n", name));
3121 ndn->name = name;
3122 ndn->device = NULL;
3123 #ifndef __AROS__
3124 ndn->port = dl->dol_Task;
3125 #else
3126 ndn->port = NULL;
3127 #endif
3128 AddTail((struct List*)ndl, (struct Node*)ndn);
3132 UnLockDosList(LDF_VOLUMES|LDF_READ);
3134 #ifndef __AROS__
3135 dl = LockDosList(LDF_DEVICES|LDF_READ);
3136 while(( dl = NextDosEntry(dl, LDF_DEVICES)))
3138 struct NewDosNode *ndn = NULL;
3140 if (!dl->dol_Task) continue;
3142 ndn = (struct NewDosNode*)List_First(ndl);
3143 while ((ndn))
3145 if (dl->dol_Task == ndn->port)
3147 STRPTR name;
3148 UBYTE *dosname = (UBYTE*)BADDR(dl->dol_Name);
3149 LONG len = dosname[0];
3151 if ((name = (STRPTR)AllocPooled(pool, len + 1)))
3153 name[len] = 0;
3154 strncpy(name, &dosname[1], len);
3157 ndn->device = name;
3158 break;
3161 ndn = (struct NewDosNode*)Node_Next(ndn);
3164 UnLockDosList(LDF_DEVICES|LDF_READ);
3165 #endif
3166 return ndl;
3168 DeletePool(pool);
3170 return NULL;
3173 static void IconVolumeList__DestroyDOSList(struct NewDosList *ndl)
3175 if (ndl && ndl->pool) DeletePool(ndl->pool);
3177 /* sba: End SimpleFind3 */
3180 struct MUI_IconVolumeData
3182 int dummy;
3185 /**************************************************************************
3186 OM_NEW
3187 **************************************************************************/
3188 IPTR IconVolumeList__OM_NEW(struct IClass *CLASS, Object *obj, struct opSet *message)
3190 struct MUI_IconDrawerData *data = NULL;
3191 struct TagItem *tag = NULL,
3192 *tags = NULL;
3194 obj = (Object *)DoSuperNewTags(CLASS, obj, NULL,
3195 TAG_MORE, (IPTR) message->ops_AttrList);
3197 if (!obj) return FALSE;
3199 data = INST_DATA(CLASS, obj);
3201 SET(obj, MUIA_IconList_DisplayFlags, ICONLIST_DISP_VERTICAL);
3202 SET(obj, MUIA_IconList_SortFlags, 0);
3204 return (IPTR)obj;
3207 /**************************************************************************
3208 MUIM_IconList_Update
3209 **************************************************************************/
3210 IPTR IconVolumeList__MUIM_IconList_Update(struct IClass *CLASS, Object *obj, struct MUIP_IconList_Update *message)
3212 //struct MUI_IconVolumeData *data = INST_DATA(CLASS, obj);
3213 struct IconEntry *this_Icon = NULL;
3214 struct NewDosList *ndl = NULL;
3216 DoMethod(obj, MUIM_IconList_Clear);
3218 /* If not in setup do nothing */
3219 if (!(_flags(obj) & MADF_SETUP)) return 1;
3221 if ((ndl = IconVolumeList__CreateDOSList()))
3223 struct NewDosNode *nd = NULL;
3224 ForeachNode(ndl, nd)
3226 char buf[300];
3227 if (nd->name)
3229 strcpy(buf, nd->name);
3230 strcat(buf, ":Disk");
3232 if (!(this_Icon = DoMethod(obj, MUIM_IconList_CreateEntry, (IPTR)buf, (IPTR)nd->name, (IPTR)NULL, (IPTR)NULL)))
3234 D(bug("[IconList]: IconVolumeList__MUIM_IconList_Update: Failed to Add IconEntry for '%s'\n", nd->name));
3236 else
3238 if (!(this_Icon->ile_Flags & ICONENTRY_FLAG_HASICON))
3239 this_Icon->ile_Flags |= ICONENTRY_FLAG_HASICON;
3241 if (!(strcmp(nd->name, "Ram Disk")))
3243 D(bug("[IconList]: IconVolumeList__MUIM_IconList_Update: Setting Ram Disks icon node priority to 5\n"));
3244 this_Icon->ile_Node.ln_Pri = 5; /// Special dirs get Priority 5
3246 #warning "TODO: Check if volume is removable and set its priority lower than fixed disks"
3247 // else if ()
3248 // {
3249 // this_Icon->ile_Node.ln_Pri = 0; /// Removable Media get Priority 0
3250 // }
3251 else this_Icon->ile_Node.ln_Pri = 1; /// Fixed Media get Priority 1
3255 IconVolumeList__DestroyDOSList(ndl);
3258 /* default display/sorting flags */
3259 DoMethod(obj, MUIM_IconList_Sort);
3261 return 1;
3265 BOOPSI_DISPATCHER(IPTR, IconVolumeList_Dispatcher, CLASS, obj, message)
3267 switch (message->MethodID)
3269 case OM_NEW: return IconVolumeList__OM_NEW(CLASS, obj, (struct opSet *)message);
3270 case MUIM_IconList_Update: return IconVolumeList__MUIM_IconList_Update(CLASS,obj,(APTR)message);
3273 return DoSuperMethodA(CLASS, obj, message);
3275 BOOPSI_DISPATCHER_END
3278 * Class descriptor.
3280 const struct __MUIBuiltinClass _MUI_IconList_desc = {
3281 MUIC_IconList,
3282 MUIC_Area,
3283 sizeof(struct MUI_IconData),
3284 (void*)IconList_Dispatcher
3287 const struct __MUIBuiltinClass _MUI_IconDrawerList_desc = {
3288 MUIC_IconDrawerList,
3289 MUIC_IconList,
3290 sizeof(struct MUI_IconDrawerData),
3291 (void*)IconDrawerList_Dispatcher
3294 const struct __MUIBuiltinClass _MUI_IconVolumeList_desc = {
3295 MUIC_IconVolumeList,
3296 MUIC_IconList,
3297 sizeof(struct MUI_IconVolumeData),
3298 (void*)IconVolumeList_Dispatcher